Rails перед действием для ActionMailer, который будет использовать аргументы почтовой программы
Предположим, у меня есть почтовик, который отправляет разные электронные письма, но, как ожидается, будет вызван с теми же параметрами. Я хочу обработать эти параметры для всех действий mailer. Итак, вызывая before_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` 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
тогда в моем контроллере / сервисе я делаю где-то
MyMailer.actionx(*mailer_params).deliver_now
как я могу получить доступ к same_param
список аргументов внутри before_action
заблокировать ?
EDIT:
Я хочу, чтобы рефакторинг от
/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
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
чувствует себя не оптимальной (prepare_mail(same_params)
дублируется в каждом действии)
следовательно, то, что было предложено выше
3 ответов
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]
обновление
Если вы используете Rails 5.1, вы можете посмотреть на ActionMailer::Параметризованные
Решение 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
альтернативное решение ниже с использованием method_missing от родительского контроллера
это не правильно, чтобы поместить свою логику там, но если вы все еще хотите это сделать, вы можете использовать method_missing, чтобы поместить свою логику там и пропустить методы action1 и action2.
исходный method_missing из 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
основываясь на ответе Сайрама, я подумал о следующем, но это кажется немного странным, не может быть сделано с before_action
обратного вызова ??
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
также я теряю все классные вещи из before_action (передавая only
или except
массив и т. д.)