Ruby 将使用mailer参数的ActionMailer的Rails before_操作
假设我有一个发送不同电子邮件的邮件程序,但预期将使用相同的参数调用它。我想为所有邮件程序操作处理这些参数。因此,在_action之前调用一个Ruby 将使用mailer参数的ActionMailer的Rails before_操作,ruby,actionmailer,ruby-on-rails-5,Ruby,Actionmailer,Ruby On Rails 5,假设我有一个发送不同电子邮件的邮件程序,但预期将使用相同的参数调用它。我想为所有邮件程序操作处理这些参数。因此,在_action之前调用一个,它将读取发送给mailer方法的参数 /mailers/my_mailer.rb class MyMailer < ApplicationMailer before_filter do |c| # c.prepare_mail # Will fail, because I need to pass `same_param` arg
,它将读取发送给mailer方法的参数
/mailers/my_mailer.rb
class MyMailer < ApplicationMailer
before_filter do |c|
# c.prepare_mail # Will fail, because I need to pass `same_param` arguments
# # I want to send the original arguments
# c.prepare_mail(same_param) # How do I get `same_param` here ?
end
def action1(same_param)
# email view is going to use @to, @from, @context
method_only_specific_to_action1
end
def action2(same_param)
# email view is going to use @to, @from, @context
method_only_specific_to_action2
end
private
def prepare_mail(same_params)
@to = same_params.recipient
@from = same_params.initiator
@context = same_params.context
end
end
如何访问before\u action
块中的same\u param
参数列表
编辑:
我想从
/mailers/my_mailer.rb
class MyMailer < ApplicationMailer
def action1(same_param)
@to = same_params.recipient
@from = same_params.initiator
@context = same_params.context
method_only_specific_to_action1
end
def action2(same_param)
@to = same_params.recipient
@from = same_params.initiator
@context = same_params.context
method_only_specific_to_action2
end
def actionx
...
end
end
/mailers/my_mailer.rb
类MyMailer
这就是重构
/mailers/my_mailer.rb
class MyMailer < ApplicationMailer
def action1(same_param)
prepare_mail(same_params)
method_only_specific_to_action1
end
def action2(same_param)
prepare_mail(same_params)
method_only_specific_to_action2
end
def actionx
...
end
private
def prepare_mail(same_params)
@to = same_params.recipient
@from = same_params.initiator
@context = same_params.context
end
end
/mailers/my_mailer.rb
类MyMailer
感觉非最佳状态(prepare\u mail(相同参数)
在每个操作中重复)
因此,上文提出了建议
解决方案1:
如果你不在乎格式,我建议你用这个
MyMailer.generic("actionx", *mailer_params).deliver_now
def generic(actiontype, *mailer_params)
# custom logic goes here to construct the to, from, etc.,
# new_options from custom logic
self.send(actiontype, new_options)
end
下面使用父控制器中缺少方法_的替代解决方案
将逻辑放在那里是不对的,但是如果您仍然想这样做,可以使用方法\u missing将逻辑放在那里,并跳过action1和action2方法
action_mailer中缺少原始方法_,可用作参考:
def method_missing(method_name, *args)
if action_methods.include?(method_name.to_s)
MessageDelivery.new(self, method_name, *args)
else
super
end
end
根据赛拉姆的回答,我想到了以下几点,但这感觉有点奇怪,难道在采取行动之前不能用回调来完成吗
class MyMailer < ApplicationMailer
# Simulation of before_action callback that would support passing the *args to the callback method
def self.method_missing(method_name, *args)
method_name = :"#{method_name.to_s}_headers_prefilled"
if action_methods.include?(method_name)
mailer = MyMailer.generic(*args) # The before_action callback that passes *args
mailer.send(method_name, *args) # The action itself
else
super
end
end
def generic(*mailer_params)
# custom logic goes here to construct the headers to, from, etc.,
end
def action1_headers_prefilled(mailer_params)
# Logic only relevant for action1
end
classmymailer
此外,我还丢失了操作前的所有酷东西(仅传递或数组除外,等等)ActionMailer使用AbstractController::Callbacks
模块。我试过了,它似乎对我有用
代码
class MyMailer < ApplicationMailer
def process_action(*args)
# process the args here
puts args
super
end
def some_mail(*args)
end
end
MyMailer.some_mail(1, 2) #=> prints ['some_mail', 1, 2]
classmymailer打印['some_mail',1,2]
更新
如果您使用的是Rails 5.1,您可以查看一下只是一个想法-您是否想过直接使用net::STMP发送电子邮件。它将比Action Mailer更具可定制性。从软件工程的角度来看,ActionMailer是一个适配器,您可以配置几种电子邮件传递方法(我目前使用的是3-4),我担心SMTP并不是世界上的全部,所以我想使用ActionMailer。我认为您正在将逻辑部分从控制器移动到层中。最好在mailer类和controller之间添加一个服务层/模型类来实现这一点,而不是覆盖默认的mailer来实现您想要的。@spickermann抱歉忘记了继承,现在添加它。您可以考虑<代码>应用程序邮件> <代码>类似<代码> ActhMaule::Base< /Cord>。在我之前的评论中,我只是解释我不仅仅是通过SMTP直接发送邮件,而且还配置为使用:file
,:cache
,:letter\u opener
,等等由ActionMailer很好地包装的传递适配器。您的问题似乎可以通过Rails 5.1中的参数化邮件程序解决(请参阅)问题是,在填写电子邮件标题时有很多不太符合逻辑的(每个操作都是一样的),但每个单独的mailer_操作都是特定的,我可能想在其中做一些额外的事情(比如附加特定的文件等)。请参阅第一个解决方案。self.send(actiontype,options)哦,对了,这真的很有意义!“对不起,一开始我没意识到它在做什么。”塞拉姆,你真的试过你的第一个建议吗?这很吸引人,但在rails 4.2下,我得到了ActionView::MissingTemplate:MissingTemplate my_-mailer/generic和“mailer”
。您将如何使用before_-action做到这一点?我试过了,但是没有,我也不知道。事实上,如果您使用的是Rails 5.1,您可以看看它实际上相当不错,可能会有什么进展,但它实际上破坏了大多数现有的测试,在编写本文时,RSpec实际上不太支持它,并且会涉及相当多的代码重写。我们尝试在不同的邮件中使用它,但在撰写本文时,它不如process\u action
class MyMailer < ApplicationMailer
def process_action(*args)
# process the args here
puts args
super
end
def some_mail(*args)
end
end
MyMailer.some_mail(1, 2) #=> prints ['some_mail', 1, 2]