Using Sorcery in Rails 7 and EffectiveResources
Nerian opened this issue · 7 comments
Hi,
I am trying to update to Rails 7 my app but I keep hitting the same issue:
➜ sample_app git:(main) rails c
/Users/Nerian/.rvm/rubies/ruby-2.7.4/lib/ruby/2.7.0/net/protocol.rb:66: warning: already initialized constant Net::ProtocRetryError
/Users/Nerian/.rvm/gems/ruby-2.7.4/gems/net-protocol-0.1.3/lib/net/protocol.rb:68: warning: previous definition of ProtocRetryError was here
/Users/Nerian/.rvm/rubies/ruby-2.7.4/lib/ruby/2.7.0/net/protocol.rb:206: warning: already initialized constant Net::BufferedIO::BUFSIZE
/Users/Nerian/.rvm/gems/ruby-2.7.4/gems/net-protocol-0.1.3/lib/net/protocol.rb:208: warning: previous definition of BUFSIZE was here
/Users/Nerian/.rvm/rubies/ruby-2.7.4/lib/ruby/2.7.0/net/protocol.rb:503: warning: already initialized constant Net::NetPrivate::Socket
/Users/Nerian/.rvm/gems/ruby-2.7.4/gems/net-protocol-0.1.3/lib/net/protocol.rb:504: warning: previous definition of Socket was here
Traceback (most recent call last):
39: from bin/rails:4:in `<main>'
38: from /Users/Nerian/.rvm/gems/ruby-2.7.4/gems/bootsnap-1.11.1/lib/bootsnap/load_path_cache/core_ext/kernel_require.rb:30:in `require'
37: from /Users/Nerian/.rvm/gems/ruby-2.7.4/gems/bootsnap-1.11.1/lib/bootsnap/load_path_cache/core_ext/kernel_require.rb:30:in `require'
36: from /Users/Nerian/.rvm/gems/ruby-2.7.4/gems/railties-7.0.2.3/lib/rails/commands.rb:18:in `<main>'
35: from /Users/Nerian/.rvm/gems/ruby-2.7.4/gems/railties-7.0.2.3/lib/rails/command.rb:48:in `invoke'
34: from /Users/Nerian/.rvm/gems/ruby-2.7.4/gems/railties-7.0.2.3/lib/rails/command/base.rb:87:in `perform'
33: from /Users/Nerian/.rvm/gems/ruby-2.7.4/gems/thor-1.2.1/lib/thor.rb:392:in `dispatch'
32: from /Users/Nerian/.rvm/gems/ruby-2.7.4/gems/thor-1.2.1/lib/thor/invocation.rb:127:in `invoke_command'
31: from /Users/Nerian/.rvm/gems/ruby-2.7.4/gems/thor-1.2.1/lib/thor/command.rb:27:in `run'
30: from /Users/Nerian/.rvm/gems/ruby-2.7.4/gems/railties-7.0.2.3/lib/rails/commands/console/console_command.rb:101:in `perform'
29: from /Users/Nerian/.rvm/gems/ruby-2.7.4/gems/railties-7.0.2.3/lib/rails/command/actions.rb:15:in `require_application_and_environment!'
28: from /Users/Nerian/.rvm/gems/ruby-2.7.4/gems/railties-7.0.2.3/lib/rails/command/actions.rb:28:in `require_environment!'
27: from /Users/Nerian/.rvm/gems/ruby-2.7.4/gems/railties-7.0.2.3/lib/rails/application.rb:348:in `require_environment!'
26: from /Users/Nerian/.rvm/gems/ruby-2.7.4/gems/zeitwerk-2.5.4/lib/zeitwerk/kernel.rb:35:in `require'
25: from /Users/Nerian/.rvm/gems/ruby-2.7.4/gems/bootsnap-1.11.1/lib/bootsnap/load_path_cache/core_ext/kernel_require.rb:30:in `require'
24: from /Users/Nerian/.rvm/gems/ruby-2.7.4/gems/bootsnap-1.11.1/lib/bootsnap/load_path_cache/core_ext/kernel_require.rb:30:in `require'
23: from /private/tmp/sample_app/config/environment.rb:5:in `<main>'
22: from /Users/Nerian/.rvm/gems/ruby-2.7.4/gems/railties-7.0.2.3/lib/rails/application.rb:372:in `initialize!'
21: from /Users/Nerian/.rvm/gems/ruby-2.7.4/gems/railties-7.0.2.3/lib/rails/initializable.rb:60:in `run_initializers'
20: from /Users/Nerian/.rvm/rubies/ruby-2.7.4/lib/ruby/2.7.0/tsort.rb:205:in `tsort_each'
19: from /Users/Nerian/.rvm/rubies/ruby-2.7.4/lib/ruby/2.7.0/tsort.rb:226:in `tsort_each'
18: from /Users/Nerian/.rvm/rubies/ruby-2.7.4/lib/ruby/2.7.0/tsort.rb:347:in `each_strongly_connected_component'
17: from /Users/Nerian/.rvm/rubies/ruby-2.7.4/lib/ruby/2.7.0/tsort.rb:347:in `call'
16: from /Users/Nerian/.rvm/rubies/ruby-2.7.4/lib/ruby/2.7.0/tsort.rb:347:in `each'
15: from /Users/Nerian/.rvm/rubies/ruby-2.7.4/lib/ruby/2.7.0/tsort.rb:349:in `block in each_strongly_connected_component'
14: from /Users/Nerian/.rvm/rubies/ruby-2.7.4/lib/ruby/2.7.0/tsort.rb:431:in `each_strongly_connected_component_from'
13: from /Users/Nerian/.rvm/rubies/ruby-2.7.4/lib/ruby/2.7.0/tsort.rb:350:in `block (2 levels) in each_strongly_connected_component'
12: from /Users/Nerian/.rvm/rubies/ruby-2.7.4/lib/ruby/2.7.0/tsort.rb:228:in `block in tsort_each'
11: from /Users/Nerian/.rvm/gems/ruby-2.7.4/gems/railties-7.0.2.3/lib/rails/initializable.rb:61:in `block in run_initializers'
10: from /Users/Nerian/.rvm/gems/ruby-2.7.4/gems/railties-7.0.2.3/lib/rails/initializable.rb:32:in `run'
9: from /Users/Nerian/.rvm/gems/ruby-2.7.4/gems/railties-7.0.2.3/lib/rails/initializable.rb:32:in `instance_exec'
8: from /Users/Nerian/.rvm/gems/ruby-2.7.4/gems/effective_resources-1.17.0/lib/effective_resources/engine.rb:24:in `block in <class:Engine>'
7: from /Users/Nerian/.rvm/gems/ruby-2.7.4/gems/activesupport-7.0.2.3/lib/active_support/lazy_load_hooks.rb:42:in `on_load'
6: from /Users/Nerian/.rvm/gems/ruby-2.7.4/gems/activesupport-7.0.2.3/lib/active_support/lazy_load_hooks.rb:42:in `each'
5: from /Users/Nerian/.rvm/gems/ruby-2.7.4/gems/activesupport-7.0.2.3/lib/active_support/lazy_load_hooks.rb:43:in `block in on_load'
4: from /Users/Nerian/.rvm/gems/ruby-2.7.4/gems/activesupport-7.0.2.3/lib/active_support/lazy_load_hooks.rb:66:in `execute_hook'
3: from /Users/Nerian/.rvm/gems/ruby-2.7.4/gems/activesupport-7.0.2.3/lib/active_support/lazy_load_hooks.rb:61:in `with_execution_control'
2: from /Users/Nerian/.rvm/gems/ruby-2.7.4/gems/activesupport-7.0.2.3/lib/active_support/lazy_load_hooks.rb:71:in `block in execute_hook'
1: from /Users/Nerian/.rvm/gems/ruby-2.7.4/gems/activesupport-7.0.2.3/lib/active_support/lazy_load_hooks.rb:71:in `class_eval'
/Users/Nerian/.rvm/gems/ruby-2.7.4/gems/effective_resources-1.17.0/lib/effective_resources/engine.rb:25:in `block (2 levels) in <class:Engine>': uninitialized constant EffectiveResources::Engine::ActsAsArchived (NameError)
I tracked this down to using both sorcery and effective_resources.
This is a base Rails straight from the generator, just adding gem 'sorcery', and gem 'effective_resources':
https://github.com/Nerian/example_sorcery_effective
Doing a rails console
gives me that error:
I am not sure what could be going on. I tried going through the code for both projects but I don't see anything weird. Any ideas?
Thanks!
I wonder if this is because the current version of Sorcery is still doing the old terrible loading method, and isn't setup properly with zeitwerk loading... I'll have to take a look. There's also some other Rails 7 compat issues that need resolved IIRC, which could be contributing to this.
I suspect Sorcery is doing something dumb while loading, combined with the essentials library attaching to a loading hook incorrectly, or improperly safeguarding against double loads or something along those lines. I honestly don't know though, would have to dig into it a bit deeper and get a better understand of how that's interacting with each other.
Hi @athix,
I created an issue on the Effective gem too and they managed to provide a fix. What they changed was the way in which the files were loaded. Perhaps this may suggest how it needs to be loaded in sorcery too:
I ran into a similar thing recently. In the initializer where i do
config.user_class = User
Rails complains that it can't find User
class.
NameError:
uninitialized constant User
# ./config/initializers/sorcery.rb:354:in `block in <top (required)>'
# ./config/environment.rb:5:in `<top (required)>'
I was able to get around it by adding several extra require
statements in the config/initializer/sorcery.rb
. Not a big deal but thought I'd mention it here.
@athix I think you're correct that the sorcery loading is not setup to work with zeitwerk. Sounds like you have plans for a v1 release so you may already have ideas on how to solve this but I wondered about whether those class specifications (like for UserMailer
, and UserProvider
, and User
) in the initializer could be strings instead of the class. Feels like that would immediately simplify the dependencies of that file.
In any case, for anyone reading, you might be able to get away with manually adding require
s for the missing classes.
On further investigation, just adding requires in the initializer
doesn't quite cut it.
Instead I used Rails.application.reloader.to_prepare do
to properly load sorcery for an initializer and it seemed to help other issues (after the require steps above I had test failures and the app was basically broken).
I basically changed my initializer/sorcery.rb
like this:
Rails.application.reloader.to_prepare do
Rails.application.config.sorcery.submodules = %I[...]
Rails.application.config.sorcery.configure do |config|
...
end
end
with no extra requires.
I found this here. Hope this helps out.
Dang.
It's been a while since I tested it, but iirc I did fix all the zeitwerk & related loading issues with v1. "Just" need to get v1 production ready, and it would probably address a couple of the Rails 7, and all of the zeitwerk, related issues.
It's definitely on my radar to make a big push for v1 ASAP, one major blocker there being writing some tests to ensure the major rewrites I've done there are production ready. The introduction of the plugin system is a massive overhaul, and considering the high risk nature of an authentication library, I don't want to rush that out the door without some thorough vetting first.
If anyone would like to help with this, a good starting place would be migrating the existing test suite to make sense for how Sorcery has been restructured in v1.
This test update work would go on the master
branch? You don't have a v1
branch in flight, right? I might be able to find a little time to look at migrating tests.
@bunnymatic The rework code is over on Sorcery/sorcery-rework, be warned that it's not production ready though, and might eat your cat.