diff --git a/lib/devise.rb b/lib/devise.rb index d4d54aeb..6ccbbc3d 100644 --- a/lib/devise.rb +++ b/lib/devise.rb @@ -305,6 +305,10 @@ module Devise defined?(ActiveRecord) && ActiveRecord.gem_version >= Gem::Version.new("5.1.x") end + def self.rails6_and_up? + Rails.gem_version >= Gem::Version.new("6.0.x") + end + # Default way to set up Devise. Run rails generate devise_install to create # a fresh initializer with all configuration values. def self.setup diff --git a/lib/devise/rails.rb b/lib/devise/rails.rb index 5cc5fa6d..34bc3644 100644 --- a/lib/devise/rails.rb +++ b/lib/devise/rails.rb @@ -43,5 +43,11 @@ module Devise ) end end + + initializer "devise.zeitwerk" do + if Devise.rails6_and_up? && Rails.autoloaders.zeitwerk_enabled? && !Object.const_defined?(Devise.parent_mailer) + Rails.autoloaders.main.ignore("#{__dir__}/app/mailers/devise/mailer.rb") + end + end end end diff --git a/test/rails_app/config/application.rb b/test/rails_app/config/application.rb index 0c844878..465d6287 100644 --- a/test/rails_app/config/application.rb +++ b/test/rails_app/config/application.rb @@ -49,5 +49,9 @@ module RailsApp if Devise::Test.rails52_and_up? && !Devise::Test.rails6? Rails.application.config.active_record.sqlite3.represent_boolean_as_integer = true end + + if Devise.rails6_and_up? + config.autoloader = :zeitwerk + end end end diff --git a/test/rails_test.rb b/test/rails_test.rb index fdc1612e..2317bbf2 100644 --- a/test/rails_test.rb +++ b/test/rails_test.rb @@ -8,4 +8,24 @@ class RailsTest < ActiveSupport::TestCase assert_equal :load_config_initializers, initializer.after assert_equal :build_middleware_stack, initializer.before end + + test 'ignore devise mailer loading when ActionMailer is not defined with zeitwerk' do + if Devise.rails6_and_up? + begin + swap Devise, parent_mailer: 'NotDefinedParentMailer' do + Devise::Engine.initializers.detect { |initializer| initializer.name == 'devise.zeitwerk' }.block.call + assert Rails.autoloaders.main.ignored_glob_patterns.any? { |pattern| pattern.include?("mailer.rb") } + end + ensure + Rails.autoloaders.main.instance_variable_set(:@ignored_glob_patterns, Set.new) + end + end + end + + test 'load devise mailer file when Devise.parent_mailer is defined with zeitwerk' do + if Devise.rails6_and_up? + Devise::Engine.initializers.detect { |initializer| initializer.name == 'devise.zeitwerk' }.block.call + refute Rails.autoloaders.main.ignored_glob_patterns.any? { |pattern| pattern.include?("mailer.rb") } + end + end end