Rails before_action for an ActionMailer that will use the mailer arguments

Suppose I have a mail program that sends different emails, but it is expected that they will be called with the same parameters. I want to process these parameters for all actions of the mail program. Thus, a before_action call that will read the parameters sent to the mailer method

 /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 

Then in my controller / service I am somewhere

 MyMailer.actionx(*mailer_params).deliver_now 

How can I access the same_param argument same_param inside the before_action block?

EDIT:

I want refactoring from

 /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 

And this refactoring

 /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 

Feels non-optimal ( prepare_mail(same_params) duplicated in every action)

Therefore, what was proposed above

+6
source share
3 answers

ActionMailer uses the AbstractController::Callbacks module. I tried this and it seems to work for me.

Code

 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] 

Documentation

+5
source

Solution1:

I would suggest you use this if you don't need a format

 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 

alternative solution below using search_ method from parent controller

It is wrong to embed your logic, but if you still want to do this, you can use the missing method to put your logic there and skip the action1 and action2 methods.

The original method_missing method from action_mailer, which can be used as a reference:

 def method_missing(method_name, *args) if action_methods.include?(method_name.to_s) MessageDelivery.new(self, method_name, *args) else super end end 

https://github.com/rails/rails/blob/c8a18aaf44a84f1ef0df007aa3f8446752dc327d/actionmailer/lib/action_mailer/base.rb#L561-L567

+1
source

Based on Sairam, answer at least the following, but it's a bit weird, could it not be done with a before_action callback ??

 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 

Also I lose all the cool stuff from before_action (passing in an array of only or except , etc.)

0
source

Source: https://habr.com/ru/post/982797/


All Articles