如何在Rails的config/production.rb文件中访问指定模型并从数据库表获取异常邮件接收地址
解决Rails中ExceptionNotification无法从数据库动态获取收件人邮箱的问题
我明白你遇到的困扰了——Rails配置文件的加载优先级确实高于ActiveRecord初始化,直接在配置阶段调用模型方法或者判断表存在性都会失败,因为此时数据库连接和模型都还没准备好。另外注意到你代码里还有个小笔误:判断条件里写的是YbNotifierEmailId,但实际模型名是YbNotifierEmailIds(少了末尾的s),这也会导致判断失效。下面给你两种可行的解决方案:
方案1:使用Proc延迟加载收件人邮箱
ExceptionNotification支持用Proc来动态获取收件人,代码会在实际发送异常邮件时才执行,此时ActiveRecord已经完全初始化,数据库连接正常,能正确读取表中的邮箱地址。
修改配置如下:
Rails.application.middleware.use ExceptionNotification::Rack, :email => { :email_prefix => "[YB-QA] ", :sender_address => %{"YB Notifier" <noreply@yb.com>}, :exception_recipients => Proc.new { # 修正模型名拼写,确保模型已定义且表存在 if defined?(YbNotifierEmailIds) && YbNotifierEmailIds.table_exists? YbNotifierEmailIds.pluck(:email_id) else %w{test@ssolution.com} end } }
这种方法的优势是:后续数据库中邮箱地址更新后,不需要重启Rails应用就能生效,因为每次发送邮件都会重新查询数据库。
方案2:利用after_initialize回调延迟配置
Rails的after_initialize回调会在所有初始化工作完成(包括ActiveRecord模型加载、数据库连接建立)后执行。把ExceptionNotification的配置放在这个回调里,就能安全读取数据库内容。
在config/initializers/exception_notification.rb文件中添加以下代码:
Rails.application.config.after_initialize do # 此时可以安全检查模型和表 recipients = if defined?(YbNotifierEmailIds) && YbNotifierEmailIds.table_exists? YbNotifierEmailIds.pluck(:email_id) else %w{test@ssolution.com} end Rails.application.middleware.use ExceptionNotification::Rack, :email => { :email_prefix => "[YB-QA] ", :sender_address => %{"YB Notifier" <noreply@yb.com>}, :exception_recipients => recipients } end
注意:这种方法会在应用启动时读取一次邮箱地址,后续数据库中邮箱更新的话,需要重启应用才能生效。
为什么原判断条件失败?
在production.rb加载时,Rails处于初始化早期阶段:
- ActiveRecord模型还未完全加载,加上你代码里的模型名拼写错误,
defined?(YbNotifierEmailId)会返回false - 数据库连接尚未建立,
table_exists?无法正确判断表是否存在
因此判断条件直接走到else分支,使用了默认邮箱。
内容的提问来源于stack exchange,提问作者Somebody_ror
相关产品推荐
相关产品推荐

