Rails7引擎中向DeviseMailer引入Concern触发NameError问题求助
在Rails 7多引擎架构中,Core引擎定义了继承自Devise::Mailer的DeviseApplicationMailer,并基于devise_invitable实现了自定义的invitation_instructions方法。现在需要在PaymentProcess引擎中通过Concern扩展该方法:仅当用户属于PaymentProcess类型时执行自定义逻辑,否则调用原方法,但执行时触发uninitialized constant PaymentProcess::DeviseApplicationMailerConcern错误。
解决方案
1. 修正Concern的命名空间与文件路径
由于PaymentProcess引擎启用了isolate_namespace,Concern必须嵌套在PaymentProcess模块下,同时文件路径要与命名空间严格对应:
调整文件路径
将原文件路径:engines/payment_process/app/mailers/concerns/devise_application_mailer_concern.rb
修改为:engines/payment_process/app/mailers/concerns/payment_process/devise_application_mailer_concern.rb
更新Concern代码
module PaymentProcess module DeviseApplicationMailerConcern extend ActiveSupport::Concern included do def invitation_instructions(resource, *args) # 修正类型判断:PaymentProcess是引擎模块,需判断具体模型(如PaymentProcess::User) if resource.is_a?(PaymentProcess::User) recipient, customer = resource scope = 'devise.mailer.invitation_instructions' @invited_by_text = invited_by_text(customer, recipient.invited_by, scope) mail = super mail.subject = I18n.t('subject', scope:) if customer.present? mail else # 调用Core引擎中的原方法 super end end end end end
2. 正确指定被扩展的邮件器类
你之前错误地给Devise::Mailer引入Concern,但实际项目中使用的是Core引擎的DeviseApplicationMailer(继承自Devise::Mailer)。修改PaymentProcess引擎的engine.rb配置:
module PaymentProcess class Engine < ::Rails::Engine engine_name 'payment_process' isolate_namespace PaymentProcess # 其他配置... config.to_prepare do # 给Core引擎的邮件器引入Concern Core::DeviseApplicationMailer.include(PaymentProcess::DeviseApplicationMailerConcern) end end end
注:如果Core引擎未启用
isolate_namespace,则直接使用DeviseApplicationMailer.include(...)即可。
3. 验证自动加载逻辑(可选)
如果仍存在加载问题,可在PaymentProcess引擎的engine.rb中显式添加concerns目录到自动加载路径:
config.autoload_paths << File.expand_path('../app/mailers/concerns', __dir__)
内容的提问来源于stack exchange,提问作者mr_muscle

