Skip to content

Use optimized loading of default configuration for test / development environments #284

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 3 commits into
base: main
Choose a base branch
from

Conversation

chaadow
Copy link
Contributor

@chaadow chaadow commented May 9, 2025

Context

While investigating our big production rails application in development/test mode, i've realized that rails routes file was loaded on startup as well as all our devise models. It was thanks to this script in this conference.

the flow is the following :
1- gem 'devise-jwt' in Gemfile
2- this registers a Railties that loads routes at initialization
3- then run a rails command such as bin/rails console or bin/rails server that triggers the rails initializaiton process
4- the hook registered by devise-jwt is run at startup
5- all routes are loaded even for rails runner or rails console or rails test ( for unit tests that don't need routes to be loaded )

this can speedup both development and test environement especially for big applications that have a lot of routes. and avoids loading ActiveRecord on startup when/if not needed

Solution

Rails recently added a hook called after_routes_loaded that triggers as the name suggests when the routes are loaded, and since devise-jwt needs the routes to be loaded in order to register the defaults for all devise models, this is I believe the perfect compromise for all environments ( test/dev and production )

cc @waiting-for-dev

Devise started the development of devise 5 in its alpha phase. I believe it's safe to have a less strict on the dependency's version
@waiting-for-dev waiting-for-dev requested a review from Copilot May 10, 2025 05:47
Copy link

@Copilot Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull Request Overview

This PR optimizes the loading of default configuration for test and development environments by adjusting when routes are loaded, thereby reducing unnecessary initialization overhead. The changes include a temporary hook in the test configuration and a replacement of the after_initialize block with an after_routes_loaded hook in the Railtie.

Reviewed Changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 2 comments.

File Description
spec/spec_helper.rb Added a before hook to conditionally reload routes for tests.
lib/devise/jwt/railtie.rb Replaced after_initialize with after_routes_loaded and removed redundant configuration reloading.

Copy link
Owner

@waiting-for-dev waiting-for-dev left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you! This is great. I think I might cut a v1.0 release now, given this will make Rails < 7.1 incompatible. However, I'm ok with that given those are only maintained in terms of security updates so we can do the same.

# TODO: Remove once Devise publishes a new version
# https://github.com/heartcombo/devise/issues/5705
config.before do
Rails.application.try(:reload_routes_unless_loaded)
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@chaadow , I'm wondering if users will also need to add this to their test suite to make them happy 🤔

Copy link
Contributor Author

@chaadow chaadow May 10, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

only those on Rails 8 and above ( because of lazy routes loading ), but most of us that are on rails 8 use the "main/master" version of devise because they have not cut a release yet :/

because if you look at the changelog: https://github.com/heartcombo/devise/blob/main/CHANGELOG.md

everything is "well supported" but it's still not released yet. and since this gem tests against the most recent version of devise ( on rubygems,) I did this workaround to make the tests pass!

Your call @waiting-for-dev 🙏🏼

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Gotcha. How about this: we could put it behind a configuration option that's disabled by default. That way, we wouldn't break anyone's existing test suites. But folks who are aware of these quirks could enable it and add the call to their spec_helper file. What do you think? It'd also be good to add a notice in the README. Once Devise releases a new version, we can clean it up.

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

By the way, for our test suite, we can probably just Rails.application.reload_routes_unless_loaded, right? Given we're using Rails 8.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@waiting-for-dev you are definitely right! I've just tested it and without it it fails. I also made a slight optimization to run it before(:suite)

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hey @chaadow , just wanted to make sure you read this from above:

How about this: we could put it behind a configuration option that's disabled by default. That way, we wouldn't break anyone's existing test suites. But folks who are aware of these quirks could enable it and add the call to their spec_helper file. What do you think? It'd also be good to add a notice in the README. Once Devise releases a new version, we can clean it up.

No hurries on my end, but I wouldn't like you to be left waiting for me

@@ -21,7 +21,7 @@ Gem::Specification.new do |spec|
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
spec.require_paths = ["lib"]

spec.add_dependency 'devise', '~> 4.0'
spec.add_dependency 'devise', '>= 4.0'
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I know i've made this change in this PR a while ago : ( #275 )

But I think we're finally ready to support devise 5. and seeing that they can cut a release at any moment ( based on the changelog i've sent below) @waiting-for-dev

@@ -10,6 +10,8 @@ gem 'rails'
gem 'sqlite3'
# Use Puma as the app server
gem 'puma'

gem 'devise', github: 'heartcombo/devise', branch: 'main'
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@waiting-for-dev I thought that making the test suite run against the main branch of devise can help us catch any breaking change early on.

this goes hand in hand with spec.add_dependency 'devise', '>= 4.0'

otherwise it won't work @waiting-for-dev

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants