我见过/使用过以下几种情况:
- 在模型方法中-相关但分离的关注点耦合度高?
- 在模型的回调函数中(例如after_save)-就我目前水平而言,这是最好的分离。
- 在控制器操作中-感觉不对,但是否有情况下这是组织代码的最聪明方式?
回答晚了,但我想对这个主题进行合理化说明:
通常,在Web应用程序中,您希望发送电子邮件,无论是直接响应客户还是作为后台任务,如果我们谈论的是类似于通讯/通知邮件的东西。
该模型基本上是数据存储映射器。其逻辑应该封装数据处理/与数据存储处理的通信。因此,插入与之不相关的逻辑有点棘手,并且在大多数情况下是错误的。让我们以一个例子为例:用户注册帐户并应收到确认电子邮件。在这种情况下,可以说,确认电子邮件是创建新帐户的直接影响。现在,尝试在控制台中创建用户而不是在Web应用程序中这样做。在这种情况下触发回调听起来很奇怪,对吧?因此,回调选项被取消了。我们是否仍然应该在模型中编写该方法?好吧,如果它是用户操作/输入的直接结果,则应保留在该工作流程中。我会在成功创建用户后将其直接编写在控制器中。在模型中复制此逻辑以在控制器中调用它实际上增加了不必要的模块化和Active Record模型从Action Mailer的依赖性。尝试考虑在许多应用程序上共享该模型,其中一些不希望使用Action Mailer。出于上述原因,我认为邮件调用应该出现在它们有意义的地方,而通常模型不是那个地方。请给我举几个它确实适用的例子。
嗯,这取决于具体情况。
我曾经使用过所有这些选项,你关于“为什么我要把它放在哪里”的观点很好。
如果我想让某个模型以特定的方式更新时每次发生一些事情,那么我会把它放在模型中。甚至可以把它放在模型的回调函数中。
有时候你只是要发送一份报告;没有任何更新。在这种情况下,我通常会有一个资源,其中包括一个index操作来发送报告。
如果邮件发送器与正在更改的模型没有实际关系,我可以考虑把它放在回调函数中。但我不经常这样做。我更可能仍然将其封装在模型中。我做过这样的事,但并不经常。
我知道已经过了一段时间,但最佳实践永不过时,对吗? :)
电子邮件在定义上是异步通信(除了确认邮件,但即使是这种情况,在确认之前也应该留出一定的延迟,是最佳实践)。
因此,在我看来,发送邮件最合理的方式是:
Rails 中的问题是没有太多回调(例如 JavaScript):我个人认为像下面这样的代码很糟糕:
after_save :callback
def callback
if test_that_is_true_once_in_the_objects_life
Mailer.send_email()
end
end
def run_with_callback(action, callback_name)
if send(action)
delay.send(callback_name)
end
end
甚至在您的应用程序中创建事件系统也是一个不错的解决方案。
但最终,这些解决方案所需的时间成本相当高,因此人们最终会在操作后将其内联编写。
def activate
[...]
user.save
Mailer.send_mail
respond_to
[...]
end
回调函数是同步编程中最接近异步编程的方式,可以在Model
和Controller
中随处调用邮件发送器。
控制器是邮件发送器的好地方,原因如下: