abevoelker/devise-passwordless

Rails 7 compatible? Getting <module:Passwordless>: uninitialized constant Devise::Mailer (NameError) Did you mean? Devise::Mailers

Closed this issue · 17 comments

on Rails 7.0.0.alpha2

my Gemfile is like so:

gem 'devise' , branch: 'main' , git: 'https://github.com/heartcombo/devise.git'
gem 'devise-passwordless'

my lock file says I have devise-passwordless 0.6.1

However, when I boot the app this way (just with either rails c or rails s), there is a crash in devise-passwordless:

/Users/jason/.rvm/gems/ruby-2.7.4/gems/devise-passwordless-0.6.1/lib/devise/passwordless/mailer.rb:5:in `module:Passwordless': uninitialized constant Devise::Mailer (NameError)

full crash here:

	61: from bin/rails:4:in `<main>'
	60: from /Users/jason/.rvm/gems/ruby-2.7.4/gems/bootsnap-1.9.1/lib/bootsnap/load_path_cache/core_ext/kernel_require.rb:31:in `require'
	59: from /Users/jason/.rvm/gems/ruby-2.7.4/gems/bootsnap-1.9.1/lib/bootsnap/load_path_cache/core_ext/kernel_require.rb:22:in `require_with_bootsnap_lfi'
	58: from /Users/jason/.rvm/gems/ruby-2.7.4/gems/bootsnap-1.9.1/lib/bootsnap/load_path_cache/loaded_features_index.rb:92:in `register'
	57: from /Users/jason/.rvm/gems/ruby-2.7.4/gems/bootsnap-1.9.1/lib/bootsnap/load_path_cache/core_ext/kernel_require.rb:23:in `block in require_with_bootsnap_lfi'
	56: from /Users/jason/.rvm/gems/ruby-2.7.4/gems/bootsnap-1.9.1/lib/bootsnap/load_path_cache/core_ext/kernel_require.rb:23:in `require'
	55: from /Users/jason/.rvm/gems/ruby-2.7.4/gems/railties-7.0.0.alpha2/lib/rails/commands.rb:18:in `<main>'
	54: from /Users/jason/.rvm/gems/ruby-2.7.4/gems/railties-7.0.0.alpha2/lib/rails/command.rb:48:in `invoke'
	53: from /Users/jason/.rvm/gems/ruby-2.7.4/gems/railties-7.0.0.alpha2/lib/rails/command/base.rb:87:in `perform'
	52: from /Users/jason/.rvm/gems/ruby-2.7.4/gems/thor-1.1.0/lib/thor.rb:392:in `dispatch'
	51: from /Users/jason/.rvm/gems/ruby-2.7.4/gems/thor-1.1.0/lib/thor/invocation.rb:127:in `invoke_command'
	50: from /Users/jason/.rvm/gems/ruby-2.7.4/gems/thor-1.1.0/lib/thor/command.rb:27:in `run'
	49: from /Users/jason/.rvm/gems/ruby-2.7.4/gems/railties-7.0.0.alpha2/lib/rails/commands/console/console_command.rb:101:in `perform'
	48: from /Users/jason/.rvm/gems/ruby-2.7.4/gems/railties-7.0.0.alpha2/lib/rails/command/actions.rb:15:in `require_application_and_environment!'
	47: from /Users/jason/.rvm/gems/ruby-2.7.4/gems/railties-7.0.0.alpha2/lib/rails/command/actions.rb:28:in `require_environment!'
	46: from /Users/jason/.rvm/gems/ruby-2.7.4/gems/railties-7.0.0.alpha2/lib/rails/application.rb:345:in `require_environment!'
	45: from /Users/jason/.rvm/gems/ruby-2.7.4/gems/zeitwerk-2.5.1/lib/zeitwerk/kernel.rb:35:in `require'
	44: from /Users/jason/.rvm/gems/ruby-2.7.4/gems/bootsnap-1.9.1/lib/bootsnap/load_path_cache/core_ext/kernel_require.rb:31:in `require'
	43: from /Users/jason/.rvm/gems/ruby-2.7.4/gems/bootsnap-1.9.1/lib/bootsnap/load_path_cache/core_ext/kernel_require.rb:22:in `require_with_bootsnap_lfi'
	42: from /Users/jason/.rvm/gems/ruby-2.7.4/gems/bootsnap-1.9.1/lib/bootsnap/load_path_cache/loaded_features_index.rb:92:in `register'
	41: from /Users/jason/.rvm/gems/ruby-2.7.4/gems/bootsnap-1.9.1/lib/bootsnap/load_path_cache/core_ext/kernel_require.rb:23:in `block in require_with_bootsnap_lfi'
	40: from /Users/jason/.rvm/gems/ruby-2.7.4/gems/bootsnap-1.9.1/lib/bootsnap/load_path_cache/core_ext/kernel_require.rb:23:in `require'
	39: from /Users/jason/Work/Api/my-app/config/environment.rb:5:in `<main>'
	38: from /Users/jason/.rvm/gems/ruby-2.7.4/gems/railties-7.0.0.alpha2/lib/rails/application.rb:369:in `initialize!'
	37: from /Users/jason/.rvm/gems/ruby-2.7.4/gems/railties-7.0.0.alpha2/lib/rails/initializable.rb:60:in `run_initializers'
	36: from /Users/jason/.rvm/rubies/ruby-2.7.4/lib/ruby/2.7.0/tsort.rb:205:in `tsort_each'
	35: from /Users/jason/.rvm/rubies/ruby-2.7.4/lib/ruby/2.7.0/tsort.rb:226:in `tsort_each'
	34: from /Users/jason/.rvm/rubies/ruby-2.7.4/lib/ruby/2.7.0/tsort.rb:347:in `each_strongly_connected_component'
	33: from /Users/jason/.rvm/rubies/ruby-2.7.4/lib/ruby/2.7.0/tsort.rb:347:in `call'
	32: from /Users/jason/.rvm/rubies/ruby-2.7.4/lib/ruby/2.7.0/tsort.rb:347:in `each'
	31: from /Users/jason/.rvm/rubies/ruby-2.7.4/lib/ruby/2.7.0/tsort.rb:349:in `block in each_strongly_connected_component'
	30: from /Users/jason/.rvm/rubies/ruby-2.7.4/lib/ruby/2.7.0/tsort.rb:415:in `each_strongly_connected_component_from'
	29: from /Users/jason/.rvm/rubies/ruby-2.7.4/lib/ruby/2.7.0/tsort.rb:415:in `call'
	28: from /Users/jason/.rvm/gems/ruby-2.7.4/gems/railties-7.0.0.alpha2/lib/rails/initializable.rb:50:in `tsort_each_child'
	27: from /Users/jason/.rvm/gems/ruby-2.7.4/gems/railties-7.0.0.alpha2/lib/rails/initializable.rb:50:in `each'
	26: from /Users/jason/.rvm/rubies/ruby-2.7.4/lib/ruby/2.7.0/tsort.rb:421:in `block in each_strongly_connected_component_from'
	25: from /Users/jason/.rvm/rubies/ruby-2.7.4/lib/ruby/2.7.0/tsort.rb:431:in `each_strongly_connected_component_from'
	24: from /Users/jason/.rvm/rubies/ruby-2.7.4/lib/ruby/2.7.0/tsort.rb:422:in `block (2 levels) in each_strongly_connected_component_from'
	23: from /Users/jason/.rvm/rubies/ruby-2.7.4/lib/ruby/2.7.0/tsort.rb:350:in `block (2 levels) in each_strongly_connected_component'
	22: from /Users/jason/.rvm/rubies/ruby-2.7.4/lib/ruby/2.7.0/tsort.rb:228:in `block in tsort_each'
	21: from /Users/jason/.rvm/gems/ruby-2.7.4/gems/railties-7.0.0.alpha2/lib/rails/initializable.rb:61:in `block in run_initializers'
	20: from /Users/jason/.rvm/gems/ruby-2.7.4/gems/railties-7.0.0.alpha2/lib/rails/initializable.rb:32:in `run'
	19: from /Users/jason/.rvm/gems/ruby-2.7.4/gems/railties-7.0.0.alpha2/lib/rails/initializable.rb:32:in `instance_exec'
	18: from /Users/jason/.rvm/gems/ruby-2.7.4/gems/railties-7.0.0.alpha2/lib/rails/engine.rb:621:in `block in <class:Engine>'
	17: from /Users/jason/.rvm/gems/ruby-2.7.4/gems/railties-7.0.0.alpha2/lib/rails/engine.rb:621:in `each'
	16: from /Users/jason/.rvm/gems/ruby-2.7.4/gems/railties-7.0.0.alpha2/lib/rails/engine.rb:622:in `block (2 levels) in <class:Engine>'
	15: from /Users/jason/.rvm/gems/ruby-2.7.4/gems/railties-7.0.0.alpha2/lib/rails/engine.rb:668:in `load_config_initializer'
	14: from /Users/jason/.rvm/gems/ruby-2.7.4/gems/activesupport-7.0.0.alpha2/lib/active_support/notifications.rb:209:in `instrument'
	13: from /Users/jason/.rvm/gems/ruby-2.7.4/gems/railties-7.0.0.alpha2/lib/rails/engine.rb:669:in `block in load_config_initializer'
	12: from /Users/jason/.rvm/gems/ruby-2.7.4/gems/bootsnap-1.9.1/lib/bootsnap/load_path_cache/core_ext/kernel_require.rb:60:in `load'
	11: from /Users/jason/.rvm/gems/ruby-2.7.4/gems/bootsnap-1.9.1/lib/bootsnap/load_path_cache/core_ext/kernel_require.rb:60:in `load'
	10: from /Users/jason/Work/Api/my-app/config/initializers/devise.rb:11:in `<main>'
	 9: from /Users/jason/.rvm/gems/ruby-2.7.4/bundler/gems/devise-8593801130f2/lib/devise.rb:307:in `setup'
	 8: from /Users/jason/Work/Api/my-app/config/initializers/devise.rb:315:in `block in <main>'
	 7: from /Users/jason/.rvm/gems/ruby-2.7.4/gems/zeitwerk-2.5.1/lib/zeitwerk/kernel.rb:35:in `require'
	 6: from /Users/jason/.rvm/gems/ruby-2.7.4/gems/bootsnap-1.9.1/lib/bootsnap/load_path_cache/core_ext/kernel_require.rb:31:in `require'
	 5: from /Users/jason/.rvm/gems/ruby-2.7.4/gems/bootsnap-1.9.1/lib/bootsnap/load_path_cache/core_ext/kernel_require.rb:22:in `require_with_bootsnap_lfi'
	 4: from /Users/jason/.rvm/gems/ruby-2.7.4/gems/bootsnap-1.9.1/lib/bootsnap/load_path_cache/loaded_features_index.rb:92:in `register'
	 3: from /Users/jason/.rvm/gems/ruby-2.7.4/gems/bootsnap-1.9.1/lib/bootsnap/load_path_cache/core_ext/kernel_require.rb:23:in `block in require_with_bootsnap_lfi'
	 2: from /Users/jason/.rvm/gems/ruby-2.7.4/gems/bootsnap-1.9.1/lib/bootsnap/load_path_cache/core_ext/kernel_require.rb:23:in `require'
	 1: from /Users/jason/.rvm/gems/ruby-2.7.4/gems/devise-passwordless-0.6.1/lib/devise/passwordless/mailer.rb:3:in `<main>'
/Users/jason/.rvm/gems/ruby-2.7.4/gems/devise-passwordless-0.6.1/lib/devise/passwordless/mailer.rb:5:in `<module:Passwordless>': uninitialized constant Devise::Mailer (NameError)
Did you mean?  Devise::Mailers

Thanks for your report. At a brief glance a couple things come to mind.

One is that it looks like Devise's mailer.rb class checks if ActionMailer is defined before it defines the Devise::Mailer instance: https://github.com/heartcombo/devise/blob/8593801130f2df94a50863b5db535c272b00efe1/app/mailers/devise/mailer.rb I assume your Rails app was installed with ActionMailer (no --skip-action-mailer)?

Another possibility is this is somehow related to the load order issue reported in heartcombo/devise#5140

Third it may be some other unknown change with Rails 7 I'm not aware of. Will try to dig in as time permits

Rails 7
I have the same issue with perfectly working Mailer but when I installed devise-passwordless it gives me error "devise/passwordless/mailer.rb:4:in `module:Passwordless': uninitialized constant Devise::Mailer (NameError)"

it does seem to be a load order issue. removing require 'devise/passwordless/mailer from the devise config and adding it to our user model seems to be a workaround for the moment.

keeping open for now to be a thread for Rails 7 passwordless. perhaps this Gem can get fix or we can discuss alternatives.

Yes please do keep it open. I'm aware of the issue just haven't had time to work on it yet

Can confirm that @maribies suggestion (relocating the require statement) works for the time being.

This should (:crossed_fingers:) be fixed now in master via d2921e0. Going to add more tests to verify before cutting a release and marking this fixed. The holdup was I wanted to figure out a way to test the gem across multiple Rails versions. It was a bit of a pain but I think I figured a solution out. Thanks all for your patience and workarounds.

Hi Guys,

First of all, thanks for an excellent gem!

Got the same uninitialized constant Devise::Mailer (NameError) while performing a migration, so I thought I'd pitch in :).

After installing the gem from the master branch, I got this error message instead: NameError: uninitialized constant ApplicationMailer.

Version information
ruby 3.1.0
Rails 7.0.2.2
gem "devise-passwordless", git: "https://github.com/abevoelker/devise-passwordless", branch: "master"

Stack trace

bash$ rails db:migrate --trace
** Invoke db:migrate (first_time)
** Invoke db:load_config (first_time)
** Invoke environment (first_time)
** Execute environment
rails aborted!
NameError: uninitialized constant ApplicationMailer

      Object.const_get(camel_cased_word)
            ^^^^^^^^^^
/Users/me/.rbenv/versions/3.1.0/lib/ruby/gems/3.1.0/gems/activesupport-7.0.2.2/lib/active_support/inflector/methods.rb:280:in `constantize'
/Users/me/.rbenv/versions/3.1.0/lib/ruby/gems/3.1.0/gems/activesupport-7.0.2.2/lib/active_support/core_ext/string/inflections.rb:74:in `constantize'
/Users/me/.rbenv/versions/3.1.0/lib/ruby/gems/3.1.0/gems/devise-4.8.1/app/mailers/devise/mailer.rb:4:in `<main>'
/Users/me/.rbenv/versions/3.1.0/lib/ruby/gems/3.1.0/gems/bootsnap-1.10.3/lib/bootsnap/load_path_cache/core_ext/kernel_require.rb:30:in `require'
/Users/me/.rbenv/versions/3.1.0/lib/ruby/gems/3.1.0/gems/bootsnap-1.10.3/lib/bootsnap/load_path_cache/core_ext/kernel_require.rb:30:in `require'
/Users/me/.rbenv/versions/3.1.0/lib/ruby/gems/3.1.0/gems/zeitwerk-2.5.4/lib/zeitwerk/kernel.rb:35:in `require'
/Users/me/.rbenv/versions/3.1.0/lib/ruby/gems/3.1.0/bundler/gems/devise-passwordless-71e89d31a326/lib/devise/passwordless/mailer.rb:2:in `<main>'
/Users/me/.rbenv/versions/3.1.0/lib/ruby/gems/3.1.0/gems/bootsnap-1.10.3/lib/bootsnap/load_path_cache/core_ext/kernel_require.rb:30:in `require'
/Users/me/.rbenv/versions/3.1.0/lib/ruby/gems/3.1.0/gems/bootsnap-1.10.3/lib/bootsnap/load_path_cache/core_ext/kernel_require.rb:30:in `require'
/Users/me/.rbenv/versions/3.1.0/lib/ruby/gems/3.1.0/gems/zeitwerk-2.5.4/lib/zeitwerk/kernel.rb:35:in `require'
/Users/me/bitbucket-proj/132bikePoc/jumpstart-pro/config/initializers/devise.rb:381:in `block in <main>'
/Users/me/.rbenv/versions/3.1.0/lib/ruby/gems/3.1.0/gems/devise-4.8.1/lib/devise.rb:307:in `setup'
/Users/me/bitbucket-proj/132bikePoc/jumpstart-pro/config/initializers/devise.rb:23:in `<main>'
/Users/me/.rbenv/versions/3.1.0/lib/ruby/gems/3.1.0/gems/bootsnap-1.10.3/lib/bootsnap/load_path_cache/core_ext/kernel_require.rb:48:in `load'
/Users/me/.rbenv/versions/3.1.0/lib/ruby/gems/3.1.0/gems/bootsnap-1.10.3/lib/bootsnap/load_path_cache/core_ext/kernel_require.rb:48:in `load'
/Users/me/.rbenv/versions/3.1.0/lib/ruby/gems/3.1.0/gems/railties-7.0.2.2/lib/rails/engine.rb:667:in `block in load_config_initializer'
/Users/me/.rbenv/versions/3.1.0/lib/ruby/gems/3.1.0/gems/activesupport-7.0.2.2/lib/active_support/notifications.rb:208:in `instrument'
/Users/me/.rbenv/versions/3.1.0/lib/ruby/gems/3.1.0/gems/railties-7.0.2.2/lib/rails/engine.rb:666:in `load_config_initializer'
/Users/me/.rbenv/versions/3.1.0/lib/ruby/gems/3.1.0/gems/railties-7.0.2.2/lib/rails/engine.rb:620:in `block (2 levels) in <class:Engine>'
/Users/me/.rbenv/versions/3.1.0/lib/ruby/gems/3.1.0/gems/railties-7.0.2.2/lib/rails/engine.rb:619:in `each'
/Users/me/.rbenv/versions/3.1.0/lib/ruby/gems/3.1.0/gems/railties-7.0.2.2/lib/rails/engine.rb:619:in `block in <class:Engine>'
/Users/me/.rbenv/versions/3.1.0/lib/ruby/gems/3.1.0/gems/railties-7.0.2.2/lib/rails/initializable.rb:32:in `instance_exec'
/Users/me/.rbenv/versions/3.1.0/lib/ruby/gems/3.1.0/gems/railties-7.0.2.2/lib/rails/initializable.rb:32:in `run'
/Users/me/.rbenv/versions/3.1.0/lib/ruby/gems/3.1.0/gems/railties-7.0.2.2/lib/rails/initializable.rb:61:in `block in run_initializers'
/Users/me/.rbenv/versions/3.1.0/lib/ruby/3.1.0/tsort.rb:228:in `block in tsort_each'
/Users/me/.rbenv/versions/3.1.0/lib/ruby/3.1.0/tsort.rb:350:in `block (2 levels) in each_strongly_connected_component'
/Users/me/.rbenv/versions/3.1.0/lib/ruby/3.1.0/tsort.rb:422:in `block (2 levels) in each_strongly_connected_component_from'
/Users/me/.rbenv/versions/3.1.0/lib/ruby/3.1.0/tsort.rb:431:in `each_strongly_connected_component_from'
/Users/me/.rbenv/versions/3.1.0/lib/ruby/3.1.0/tsort.rb:421:in `block in each_strongly_connected_component_from'
/Users/me/.rbenv/versions/3.1.0/lib/ruby/gems/3.1.0/gems/railties-7.0.2.2/lib/rails/initializable.rb:50:in `each'
/Users/me/.rbenv/versions/3.1.0/lib/ruby/gems/3.1.0/gems/railties-7.0.2.2/lib/rails/initializable.rb:50:in `tsort_each_child'
/Users/me/.rbenv/versions/3.1.0/lib/ruby/3.1.0/tsort.rb:415:in `call'
/Users/me/.rbenv/versions/3.1.0/lib/ruby/3.1.0/tsort.rb:415:in `each_strongly_connected_component_from'
/Users/me/.rbenv/versions/3.1.0/lib/ruby/3.1.0/tsort.rb:349:in `block in each_strongly_connected_component'
/Users/me/.rbenv/versions/3.1.0/lib/ruby/3.1.0/tsort.rb:347:in `each'
/Users/me/.rbenv/versions/3.1.0/lib/ruby/3.1.0/tsort.rb:347:in `call'
/Users/me/.rbenv/versions/3.1.0/lib/ruby/3.1.0/tsort.rb:347:in `each_strongly_connected_component'
/Users/me/.rbenv/versions/3.1.0/lib/ruby/3.1.0/tsort.rb:226:in `tsort_each'
/Users/me/.rbenv/versions/3.1.0/lib/ruby/3.1.0/tsort.rb:205:in `tsort_each'
/Users/me/.rbenv/versions/3.1.0/lib/ruby/gems/3.1.0/gems/railties-7.0.2.2/lib/rails/initializable.rb:60:in `run_initializers'
/Users/me/.rbenv/versions/3.1.0/lib/ruby/gems/3.1.0/gems/railties-7.0.2.2/lib/rails/application.rb:372:in `initialize!'
/Users/me/bitbucket-proj/132bikePoc/jumpstart-pro/config/environment.rb:5:in `<main>'
/Users/me/.rbenv/versions/3.1.0/lib/ruby/gems/3.1.0/gems/bootsnap-1.10.3/lib/bootsnap/load_path_cache/core_ext/kernel_require.rb:30:in `require'
/Users/me/.rbenv/versions/3.1.0/lib/ruby/gems/3.1.0/gems/bootsnap-1.10.3/lib/bootsnap/load_path_cache/core_ext/kernel_require.rb:30:in `require'
/Users/me/.rbenv/versions/3.1.0/lib/ruby/gems/3.1.0/gems/zeitwerk-2.5.4/lib/zeitwerk/kernel.rb:35:in `require'
/Users/me/.rbenv/versions/3.1.0/lib/ruby/gems/3.1.0/gems/railties-7.0.2.2/lib/rails/application.rb:348:in `require_environment!'
/Users/me/.rbenv/versions/3.1.0/lib/ruby/gems/3.1.0/gems/railties-7.0.2.2/lib/rails/application.rb:510:in `block in run_tasks_blocks'
/Users/me/.rbenv/versions/3.1.0/lib/ruby/gems/3.1.0/gems/rake-13.0.6/lib/rake/task.rb:281:in `block in execute'
/Users/me/.rbenv/versions/3.1.0/lib/ruby/gems/3.1.0/gems/rake-13.0.6/lib/rake/task.rb:281:in `each'
/Users/me/.rbenv/versions/3.1.0/lib/ruby/gems/3.1.0/gems/rake-13.0.6/lib/rake/task.rb:281:in `execute'
/Users/me/.rbenv/versions/3.1.0/lib/ruby/gems/3.1.0/gems/rake-13.0.6/lib/rake/task.rb:219:in `block in invoke_with_call_chain'
/Users/me/.rbenv/versions/3.1.0/lib/ruby/gems/3.1.0/gems/rake-13.0.6/lib/rake/task.rb:199:in `synchronize'
/Users/me/.rbenv/versions/3.1.0/lib/ruby/gems/3.1.0/gems/rake-13.0.6/lib/rake/task.rb:199:in `invoke_with_call_chain'
/Users/me/.rbenv/versions/3.1.0/lib/ruby/gems/3.1.0/gems/rake-13.0.6/lib/rake/task.rb:243:in `block in invoke_prerequisites'
/Users/me/.rbenv/versions/3.1.0/lib/ruby/gems/3.1.0/gems/rake-13.0.6/lib/rake/task.rb:241:in `each'
/Users/me/.rbenv/versions/3.1.0/lib/ruby/gems/3.1.0/gems/rake-13.0.6/lib/rake/task.rb:241:in `invoke_prerequisites'
/Users/me/.rbenv/versions/3.1.0/lib/ruby/gems/3.1.0/gems/rake-13.0.6/lib/rake/task.rb:218:in `block in invoke_with_call_chain'
/Users/me/.rbenv/versions/3.1.0/lib/ruby/gems/3.1.0/gems/rake-13.0.6/lib/rake/task.rb:199:in `synchronize'
/Users/me/.rbenv/versions/3.1.0/lib/ruby/gems/3.1.0/gems/rake-13.0.6/lib/rake/task.rb:199:in `invoke_with_call_chain'
/Users/me/.rbenv/versions/3.1.0/lib/ruby/gems/3.1.0/gems/rake-13.0.6/lib/rake/task.rb:243:in `block in invoke_prerequisites'
/Users/me/.rbenv/versions/3.1.0/lib/ruby/gems/3.1.0/gems/rake-13.0.6/lib/rake/task.rb:241:in `each'
/Users/me/.rbenv/versions/3.1.0/lib/ruby/gems/3.1.0/gems/rake-13.0.6/lib/rake/task.rb:241:in `invoke_prerequisites'
/Users/me/.rbenv/versions/3.1.0/lib/ruby/gems/3.1.0/gems/rake-13.0.6/lib/rake/task.rb:218:in `block in invoke_with_call_chain'
/Users/me/.rbenv/versions/3.1.0/lib/ruby/gems/3.1.0/gems/rake-13.0.6/lib/rake/task.rb:199:in `synchronize'
/Users/me/.rbenv/versions/3.1.0/lib/ruby/gems/3.1.0/gems/rake-13.0.6/lib/rake/task.rb:199:in `invoke_with_call_chain'
/Users/me/.rbenv/versions/3.1.0/lib/ruby/gems/3.1.0/gems/rake-13.0.6/lib/rake/task.rb:188:in `invoke'
/Users/me/.rbenv/versions/3.1.0/lib/ruby/gems/3.1.0/gems/rake-13.0.6/lib/rake/application.rb:160:in `invoke_task'
/Users/me/.rbenv/versions/3.1.0/lib/ruby/gems/3.1.0/gems/rake-13.0.6/lib/rake/application.rb:116:in `block (2 levels) in top_level'
/Users/me/.rbenv/versions/3.1.0/lib/ruby/gems/3.1.0/gems/rake-13.0.6/lib/rake/application.rb:116:in `each'
/Users/me/.rbenv/versions/3.1.0/lib/ruby/gems/3.1.0/gems/rake-13.0.6/lib/rake/application.rb:116:in `block in top_level'
/Users/me/.rbenv/versions/3.1.0/lib/ruby/gems/3.1.0/gems/rake-13.0.6/lib/rake/application.rb:125:in `run_with_threads'
/Users/me/.rbenv/versions/3.1.0/lib/ruby/gems/3.1.0/gems/rake-13.0.6/lib/rake/application.rb:110:in `top_level'
/Users/me/.rbenv/versions/3.1.0/lib/ruby/gems/3.1.0/gems/railties-7.0.2.2/lib/rails/commands/rake/rake_command.rb:24:in `block (2 levels) in perform'
/Users/me/.rbenv/versions/3.1.0/lib/ruby/gems/3.1.0/gems/rake-13.0.6/lib/rake/application.rb:186:in `standard_exception_handling'
/Users/me/.rbenv/versions/3.1.0/lib/ruby/gems/3.1.0/gems/railties-7.0.2.2/lib/rails/commands/rake/rake_command.rb:24:in `block in perform'
/Users/me/.rbenv/versions/3.1.0/lib/ruby/gems/3.1.0/gems/rake-13.0.6/lib/rake/rake_module.rb:59:in `with_application'
/Users/me/.rbenv/versions/3.1.0/lib/ruby/gems/3.1.0/gems/railties-7.0.2.2/lib/rails/commands/rake/rake_command.rb:18:in `perform'
/Users/me/.rbenv/versions/3.1.0/lib/ruby/gems/3.1.0/gems/railties-7.0.2.2/lib/rails/command.rb:51:in `invoke'
/Users/me/.rbenv/versions/3.1.0/lib/ruby/gems/3.1.0/gems/railties-7.0.2.2/lib/rails/commands.rb:18:in `<main>'
/Users/me/.rbenv/versions/3.1.0/lib/ruby/gems/3.1.0/gems/bootsnap-1.10.3/lib/bootsnap/load_path_cache/core_ext/kernel_require.rb:30:in `require'
/Users/me/.rbenv/versions/3.1.0/lib/ruby/gems/3.1.0/gems/bootsnap-1.10.3/lib/bootsnap/load_path_cache/core_ext/kernel_require.rb:30:in `require'
bin/rails:4:in `<main>'
Tasks: TOP => db:migrate => db:load_config => environment

@githubble01 That's an odd error - this gem doesn't make any direct reference to ApplicationMailer but rather Devise::Mailer (as you can see from your stack trace). Devise in turn may reference ApplicationMailer through its parent_mailer logic. I'd check to make sure you have ActionMailer installed, and if so, and you don't want to use ApplicationMailer, set the config.parent_mailer option in config/initializers/devise.rb to whatever parent mailer class you prefer to use (looking at the latest Devise generator it should default to ActionMailer::Base so presumably your Devise config has already overridden this?).

Closing this as presumed fixed in 0.7.0. @githubble01 feel free to open a new issue if you keep having problems.

I'm seeing this issue too. It looks to me like if you tell devise to extend ApplicationMailer, then when we set config.mailer = "Devise::Passwordless::Mailer" this evaluates "Devise::Passwordless::Mailer" immediately, then evaluates the parent classes (Devise::Mailer and then ApplicationMailer). ApplicationMailer hasn't been loaded yet when we are in the initialisers, so it fails. The problem with this theory is it doesn't explain why it works without devise-passwordless, as by default the config.mailer is Devise::Mailer which would also extend the ApplicationMailer in this situation, but doesn't crash.

@iainbeeston -- @abevoelker says it was fixed in master above #9 (comment)
are you on that release?

I have not tried it myself.

Yes I am on the latest release (0.7.1) and it has that change 🙁

I can see why that require would fix part of the issue, I think requiring “ApplicationMailer” (in my case) would fix the issue, but it seems weird to need to do that (because devise itself doesn’t)

I've investigated this some more. What seems to be happening is this:

  • The instructions in the readme say to require "devise/passwordless/mailer" in the devise.rb initializer
  • This loads Devise::Passwordless::Mailer in the initializer and in turn loads Devise::Mailer, which in turn tries to load Devise.parent_mailer
  • This is before the application code is loaded, so at this point ApplicationMailer hasn't been loaded yet, and so the error is thrown.

So how is that different to deivse without passwordless? Without passwordless devise loads Devise::Mailer only when it's used (at runtime when in development). This works because devise takes the parent_mailer string and calls Constantine on it. At that point we're past the initialization phase and so ApplicationMailer has been loaded and everything works fine.

So what happens if you don't require "devise/passwordless/mailer"? When you try to send magic link email rails can't find Devise::Passwordless::Mailer, and throws an uninitialized constant error. What's really bugging me is why does this work for devise but not for passwordless? Devise doesn't explicitly load the devise mailer anywhere, yet when it's referenced it's loaded just fine. When devise-passwordless does the same thing, it throws an error. I'd have assumed that in modern versions of rails zeitwerk should automatically load the file for us when we reference the constant, but that isn't happening either 🤷

blqke commented

I you still encounter this same problem like I did with version 0.7.1, making a small adjustment in the config file might solve it.

The crux is to move this gem conf part:

# ==> Configuration for :magic_link_authenticatable
# Need to use a custom Devise mailer in order to send magic links
require "devise/passwordless/mailer"
config.mailer = "Devise::Passwordless::Mailer"
...
...
...

to the beginning of the Devise.setup do |config| block in config/initializers/devise.rb.

In my case, the uninitialized constant Devise::Mailer (NameError) Did you mean? Devise::Mailers appeared when devise-passwordless was used in combination with https://github.com/scambra/devise_invitable.

Thanks all for your reports and debugging feedback on this over the past couple years! ❤️

With the release of v1.0, I believe any lingering uninitialized constant issues should be resolved as I moved the mailer into a Rails engine, so that we're now working with the Rails autoloader instead of against it. If this was a showstopper for you before I'd encourage you to give it another try (the setup has also been simplified), and if you're on 0.x here's the upgrade guide: https://github.com/abevoelker/devise-passwordless/blob/master/UPGRADING.md (one change being the require "devise/passwordless/mailer" is no longer needed)