2015-02-20 15 views
6

Giả sử tôi có một bưu phẩm gửi các email khác nhau, nhưng dự kiến ​​sẽ được gọi với cùng các thông số. Tôi muốn xử lý các thông số đó cho tất cả các hành động gửi thư. Vì vậy, gọi một before_action mà có thể đọc các thông số gửi đến phương pháp bưu phẩmRails before_action cho ActionMailer có thể sử dụng đối số bưu phẩm

/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 

Sau đó, trong điều khiển của tôi/dịch vụ tôi làm ở đâu đó

MyMailer.actionx(*mailer_params).deliver_now 

Làm thế nào tôi có thể truy cập vào same_param luận danh sách bên trong khối before_action ?

EDIT:

Tôi muốn cấu trúc lại từ

/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 

Và đây 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 

Cảm thấy không tối ưu (prepare_mail(same_params) nhân đôi trong mọi hành động)

Do đó những gì đã được đề xuất ở trên

+0

chỉ là một suy nghĩ - bạn có nghĩ vì chỉ sử dụng net :: STMP trực tiếp để gửi email http://ruby-doc.org/stdlib-2.0.0 /libdoc/net/smtp/rdoc/Net/SMTP.html.Nó sẽ có thể tùy chỉnh nhiều hơn Action Mailer. – zee

+0

Từ quan điểm kỹ thuật phần mềm, ActionMailer là một bộ điều hợp và bạn có thể cấu hình một số phương thức gửi email (Tôi hiện đang sử dụng 3-4), tôi e rằng SMTP không phải là tất cả trên thế giới, vì vậy tôi muốn sử dụng ActionMailer. –

+0

Tôi nghĩ rằng bạn đang di chuyển một phần logic từ bộ điều khiển vào lớp. Tốt nhất của nó để thêm một lớp dịch vụ/mô hình lớp ở giữa các lớp mailer và bộ điều khiển để đạt được điều này hơn là ghi đè các mailer mặc định để đạt được những gì bạn muốn. – Sairam

Trả lời

5

ActionMailer sử dụng các mô-đun AbstractController::Callbacks. Tôi đã thử nó và nó có vẻ làm việc cho tôi.

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] 

The documentation

1

Solution1:

tôi sẽ đề nghị bạn sử dụng này nếu bạn không quan tâm đến định dạng

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 

giải pháp thay thế dưới đây sử dụng method_missing từ bộ điều khiển cha mẹ

Nó không đúng để đưa logic của bạn ở đó, nhưng nếu bạn vẫn muốn làm điều đó, bạn có thể sử dụng e method_missing để đặt logic của bạn ở đó và bỏ qua các phương thức action1 và action2.

method_missing gốc từ action_mailer mà có thể được sử dụng như một tài liệu tham khảo:

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

+0

Vấn đề là có rất nhiều 'không thực sự logic' bao gồm điền vào các tiêu đề email (và chúng giống nhau cho mọi hành động) , nhưng mỗi mailer_action riêng lẻ vẫn còn cụ thể và tôi có thể muốn thực hiện các công cụ bổ sung trong đó (như đính kèm một tệp cụ thể, v.v.) –

+0

xem giải pháp đầu tiên. self.send (actiontype, tùy chọn) – Sairam

+0

Oh đúng thực sự có ý nghĩa! Xin lỗi đã không nhận ra những gì nó đã làm lúc đầu. –

0

Dựa trên câu trả lời Tôi mặc dù Sairam của sau nhưng mà cảm thấy một chút lạ, nó không thể được thực hiện với before_action gọi lại ??

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 

Ngoài ra tôi mất tất cả những thứ mát mẻ từ before_action (đi qua một only hoặc except mảng, vv)

Các vấn đề liên quan