ruby-on-rails - Rails NoMethodError(nil:NilClass 的未定义方法 `humanize')发送至:
问题描述
我在我的 Rails 应用中有这样的工作:
class NewAnswerNotifyJob < ApplicationJob
queue_as :default
def perform(answer)
Services::NewAnswerNotify.new.send_notify(answer)
end
end
Services::NewAnswerNotify
:
class Services::NewAnswerNotify
def send_notify(answer)
NewAnswerNotifyMailer.new.notify(answer)
end
end
NewAnswerNotifyMailer
:
class NewAnswerNotifyMailer < ApplicationMailer
def notify(answer)
@answer = answer
@question = answer.question
@author = answer.question.author
mail to: @author.email
end
end
当我尝试在 Rails 控制台中运行时(我在开发服务器上遇到了这个问题,然后在控制台中重放了这个行为)运行Services::NewAnswerNotify#send_notify
时出现answer
了这样的错误:
2.6.0 :023 > answer = Answer.first
Answer Load (0.5ms) SELECT "answers".* FROM "answers" ORDER BY "answers"."best_solution" DESC LIMIT $1 [["LIMIT", 1]]
=> #<Answer id: 76, body: "answer body", question_id: 2, created_at: "2019-05-01 18:43:16", updated_at: "2019-05-28 15:38:16", author_id: 1, best_solution: true>
2.6.0 :024 > Services::NewAnswerNotify.new.send_notify(answer)
Question Load (0.6ms) SELECT "questions".* FROM "questions" WHERE "questions"."id" = $1 LIMIT $2 [["id", 2], ["LIMIT", 1]]
User Load (0.4ms) SELECT "users".* FROM "users" WHERE "users"."id" = $1 LIMIT $2 [["id", 1], ["LIMIT", 1]]
Traceback (most recent call last):
3: from (irb):24
2: from app/services/new_answer_notify.rb:3:in `send_notify'
1: from app/mailers/new_answer_notify_mailer.rb:8:in `notify'
NoMethodError (undefined method `humanize' for nil:NilClass)
2.6.0 :025 >
因此,错误发生在mail to: @author.email
line in 中NewAnswerNotifyMailer
,但是当邮件程序按计划工作时:
2.6.0 :025 > answer = Answer.first
Answer Load (0.7ms) SELECT "answers".* FROM "answers" ORDER BY "answers"."best_solution" DESC LIMIT $1 [["LIMIT", 1]]
=> #<Answer id: 76, body: "for flexbox grid columns also means you can set th...", question_id: 2, created_at: "2019-05-01 18:43:16", updated_at: "2019-05-28 15:38:16", author_id: 1, best_solution: true>
2.6.0 :026 > NewAnswerNotifyMailer.notify(answer)
Question Load (0.5ms) SELECT "questions".* FROM "questions" WHERE "questions"."id" = $1 LIMIT $2 [["id", 2], ["LIMIT", 1]]
User Load (0.3ms) SELECT "users".* FROM "users" WHERE "users"."id" = $1 LIMIT $2 [["id", 1], ["LIMIT", 1]]
[i18n-debug] en.new_answer_notify_mailer.notify.subject => nil
Rendering new_answer_notify_mailer/notify.html.slim within layouts/mailer
Rendered new_answer_notify_mailer/notify.html.slim within layouts/mailer (4.7ms)
Rendering new_answer_notify_mailer/notify.text.slim within layouts/mailer
Rendered new_answer_notify_mailer/notify.text.slim within layouts/mailer (3.5ms)
NewAnswerNotifyMailer#notify: processed outbound mail in 100.5ms
=> #<Mail::Message:70164808395160, Multipart: true, Headers: <From: from@example.com>, <To: codcore@gmail.com>, <Subject: Notify>, <Mime-Version: 1.0>, <Content-Type: multipart/alternative; boundary="--==_mimepart_5d0cac2d80291_b85a3fd081039fd052340"; charset=UTF-8>>
我无法意识到问题出在哪里,为什么我会Nil
在Services::NewAnswerNotify
.
解决方案
几个建议:
- 您应该直接使用 ActionMailer 类方法,而不是使用
new
. 这大概就是bug的来源 - 由于您
NewAnswerNotify
嵌套在 下Services
,因此使用根命名空间也不会那么模棱两可::NewAnswerNotifyMailer
(有些人可能不同意我的观点,但我过去有很多根命名空间错误,因此我倾向于系统地使用::
前缀现在) - 当心类加载对于
class Services::NewAnswerNotify
和module Services class NewAnswerNotification
(关于这个主题的许多现有问题)的工作方式不同
module Services
class NewAnswerNotify
def send_notify(answer)
::NewAnswerNotifyMailer.notify(answer).deliver_now # instead of .new.notify
end
end
end
还有一些关于变量和英语的侧面评论
我宁愿用
Services::NewAnswerNotification
NewAnswerNotificationMailer
def send_notification(answer)
或者def notify(answer)
从长远来看,也许是在维护代码库之后的最后一条经验建议:更明确地说明您要通知谁,def notify_question_author_of_new_answer
因为稍后您可能notify_question_subscribers_of_new_answer
需要通知一个或其他人(这完全取决于当然是您的商业模式,请随意忽略此评论)
推荐阅读
- c++ - 将 32 位大端有符号整数转换为有符号小端整数
- java - 使用 JavaParser 更改方法级别的字符串变量
- c++ - 包含模板的向量在推回时引发错误
- javascript - 使用异步瀑布时模型的响应未定义
- c# - 如何编写一个 C# 方法,该方法将使用 String[] 和 List 检索目录树中的所有目录
? - jquery - 在jquery中将两个json值相加
- vba - Excel VBA 无法获取 WorksheetFunction 类的 Match 属性
- ruby - 在 ActiveAdmin 中编辑表单时,您能否将 Update 操作覆盖为 Create 而不是 Update?
- python - 使用 curses lib getstr() 函数的 Python 交互式控制台不等待用户输入
- javascript - 在 Redux 中测试选择器的过滤状态