ActionMailer最佳实践:模型或控制器中的调用方法?

通常在对模型执行操作后调用发送电子邮件,但电子邮件本身是查看操作。 我正在寻找你如何思考哪些问题要问自己确定动作邮件方法调用的位置。

我见过/使用过它们:

  • 在模型方法中 – 相关但单独关注的错误耦合?
  • 在模型的回调中(例如after_save) – 就我目前的知识水平而言,最好的分离。
  • 在控制器操作中 – 只是感觉不对,但有没有情况这是构建代码的最明智的方法?

如果我想知道如何编程我需要像程序员一样思考,那么学习如何通过特定的编程解决方案进行思考就值得花几个月独立编码。 谢谢!

迟到的答案,但我想在这个问题上合理化:

通常,在Web应用程序中,您希望将电子邮件作为对客户端的直接反应发送。 或者作为后台任务,以防我们谈论时事通讯/通知邮件。

该模型基本上是一个数据存储映射器。 它的逻辑应该封装数据处理/通信与数据存储处理。 因此,插入与其无关的逻辑有点棘手,而且在大多数情况下是错误的。 我们举个例子:用户注册一个帐户,我们会收到一封确认电子邮件。 在这种情况下,可以说,确认电子邮件是创建新帐户的直接影响。 现在,尝试在控制台中创建用户,而不是在Web应用程序中执行此操作。 在这种情况下触发回调听起来不对,对吧? 因此,回调选项被刮伤了。 我们还应该在模型中编写方法吗? 好吧,如果它是用户操作/输入的直接影响,那么它应该保留在该工作流程中。 用户成功创建后,我会在控制器中编写它。 直。 无论如何,在要在控制器中调用的模型中复制此逻辑会增加不必要的模块性,以及来自Action Mailer的Active Record模型的依赖性。 尝试考虑在许多应用程序上共享模型,其中一些应用程序不需要Action Mailer。 由于上述原因,我认为邮件程序调用应该是有意义的,通常模型不是那个地方。 试着给我一些它做的例子。

嗯,取决于。

我已经使用了所有这些选项和你的观点’我为什么要把它放在哪里?’ 很好。

如果我想在每次以某种方式更新模型时发生这种情况,那么我将其放入模型中。 甚至可能在模型的回调中。

有时你只是在发布一份报告; 什么都没有更新。 在这种情况下,我通常会得到一个带有索引操作的资源来发送报告。

如果邮件程序与正在更改的模型没有真正关联,我可以看到将其置于回调中。 我不经常这样做。 我更有可能将其封装在模型中。 我已经完成了,不经常这样做。

我知道它已经有一段时间了但是最好的做法永远不会死,对吧? 🙂

根据定义,电子邮件异步通信(除了确认电子邮件,但即使是这个也应该是在必须确认之前留下延迟的最佳做法)。

因此,在我看来,最合乎逻辑的发送方式是:

  • 在后台动作中(使用Sidekiq或delayed_job )
  • 在一个回调方法中:“嘿,这个动作成功完成了,也许我们现在可以告诉世界了?”

Rails中的问题是它没有太多的回调(例如在JS中):我个人觉得它很脏,代码如下:

 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 

这是同步编程中最接近回调的方式,也是Mailers随处调用的结果(在ModelController )。

控制器是邮寄的好地方有几个原因:

  • 与模型无关的电子邮件。
  • 如果您的电子邮件依赖于几个彼此不了解的模型。
  • 将模型提取到API不应该意味着重新实现邮件程序。
  • 邮件程序内容由您不想传递给模型的请求变量确定。
  • 如果您的业务模型需要大量不同的电子邮件,则可以堆叠模型回调。
  • 如果电子邮件不依赖于模型计算的结果。