Rails Mailer报错:undefined method `[]' for nil:NilClass 求助
问题分析
报错undefined method []' for nil:NilClass的核心原因是**你同时在两个地方触发了邮件发送,其中模型的before_destroy回调没有传递agreement`参数**:
- 控制器的
destroy方法里,你用UserMailer.with(agreement: @agreement).agreement_delete.deliver_later正确传递了参数,这部分邮件能正常发送; - 但模型的
before_destroy :check_delete回调里,直接调用UserMailer.agreement_delete.deliver,没有传递任何参数,导致邮件器里的params[:agreement]为nil,触发报错。
创建时邮件能正常工作,是因为创建场景下的邮件调用肯定传递了agreement参数(比如类似with(agreement: @agreement)的写法),和删除时的错误场景不匹配。
解决方案
步骤1:移除重复的模型回调
删掉agreement.rb里的before_destroy回调及对应方法,避免重复触发无参数的邮件调用:
# 移除以下代码 before_destroy :check_delete private def check_delete UserMailer.agreement_delete.deliver end
步骤2:优化邮件器代码(可选,提升可读性)
Rails邮件器支持直接在方法中定义参数,比依赖params更直观:
def agreement_delete(agreement) @agreement = agreement @sent_user = User.find(@agreement.user_id) @user = User.find(@agreement.thought.user_id) @user_email = @user.email mail(to: @user_email, subject: "It's been deleted!") end
对应的控制器调用修改为:
def destroy @agreement = Agreement.find(params[:id]) UserMailer.agreement_delete(@agreement).deliver_later @agreement.destroy redirect_back end
步骤3:确认邮件触发时机(可选)
如果需要确保邮件在对象删除前发送完成(而非异步入队),可将deliver_later改为deliver_now,但异步发送更推荐,避免阻塞请求:
UserMailer.agreement_delete(@agreement).deliver_now
修改后即可解决参数nil的报错问题,同时保证邮件正常发送。
内容的提问来源于stack exchange,提问作者superbot
相关产品推荐
相关产品推荐

