0

Rails 4.2 Руби 2,3Сохранение текущего дополнительного охвата маршрута перед вызовом deliver_later на рельсах Мейлер

У меня есть два дополнительных маршрутизации областей, относящиеся к местности информации. Они установлены в before_action в application_controller, который настраивает метод default_url_options. т.е.

# app/controllers/application_controller 
# simplified version, usually has two locale values, 
# locale_lang and locale_city 


before_action :redirect_to_locale_unless_present 

private 

# If params[:locale] is not set then 
# redirect to the correct locale base on request data  
def redirect_to_locale_unless_present 
    unless params[:locale].present? 
    redirect_to url_for(locale: request.location.country_code) 
    end 
end 

def default_url_options(options = {} 
    { locale_lang: params[:locale_lang] }.merge(options) 
end 

В прицелы locale_lang и locale_city, которые в конечном итоге выглядит что-то вроде http://localhost:3000/fr/ или http://localhost:3000/en/

Это все работает, как предполагалось в браузере, однако я хотел бы использовать ActionMailer :: DeliveryJob для отправки писем в фоновых процессах. Очевидная проблема заключается в том, что ActionMailer :: DeliveryJob не сохраняет значение params[:locale].

Я хотел был бы иметь возможность позвонить SomeMailer.generic_email(options).deliver_later и отправить это сообщение default_url_options в ActionMailer :: DeliveryJob, который затем передаст их по цепочке и будет использовать их при фактической обработке почты. Я мог бы, конечно, определить default_url_options в качестве параметра для каждого метода Mailer, но я бы скорее настроил приложение, чтобы оно было автоматически включено.

Вы когда-нибудь сталкивались с этой проблемой или имели какие-либо предложения о том, как подойти к задаче. Имейте в виду, что он также должен быть потокобезопасным.

Мои в настоящее время подход заключается в отсутствии, чтобы сохранить текущий запрос в Thread.current, а затем получить те, когда enqueue_delivery вызывается через .deliver_later. то я хотел, чтобы переопределить ActionMailer :: DeliveryJob «s выполнить метод принять url_options и использовать class_eval для определения default_url_options метода в классе тока мэйлера. Однако выполнение не кажется даже вызванным при использовании deliver_later любых идей?

class ApplicationController 
    before_action :store_request 

    private 

    def store_request 
    Thread.current['actiondispatch.request'] = request 
    end 
end 

module DeliverLaterWithLocale 
    module MessageDeliveryOverrides 
    def enqueue_delivery(delivery_method, options={}) 
     args = [ 
     @mailer.name, 
     @mail_method.to_s, 
     delivery_method.to_s, 
     url_options, 
     *@args 
     ] 
     ActionMailer::DeliveryJob.set(options).perform_later(*args) 
    end 

    private 

    def url_options 
     options = {} 
     request = Thread.current["actiondispatch.request"] 
     if request 
     host  = request.host 
     port  = request.port 
     protocol = request.protocol 
     lang = request.params[:locale_lang] 
     city = request.params[:locale_city] 
     standard_port = request.standard_port 
     options[:protocol] = protocol 
     options[:host]  = host 
     options[:port]  = port if port != standard_port 
     options[:locale_lang] = lang 
     options[:locale_city] = city 
     end 
     ActionMailer::Base.default_url_options.merge(options) 
    end 
    end 

    module DeliveryJobOverrides 
    def perform(mailer, mail_method, delivery_method, url_options, *args) 
     mailer = mailer.constantize.public_send(mail_method, *args) 
     Kernel.binding.pry 
     mailer.class_eval <<-RUBY, __FILE__, __LINE__ + 1 
     def default_url_options_with_options(*args) 
      default_url_options_without_current_request(*args).merge(url_options) 
     end 
     alias_method_chain :default_url_options, :options 
     RUBY 
     mailer.send(delivery_method) 
    end 
    end 
end 

ответ

1

Incase кто-то еще хочет это сделать. Я установил его, добавив

class ApplicationController 
    before_action :store_request 

    private 

    def store_request 
    Thread.current['actiondispatch.request'] = request 
    end 
end 

module DeliverLaterWithLocale 
    module MessageDeliveryOverrides 
    def enqueue_delivery(delivery_method, options={}) 
     args = [ 
     @mailer.name, 
     @mail_method.to_s, 
     delivery_method.to_s, 
     url_options, 
     *@args 
     ] 
     ActionMailer::DeliveryJob.set(options).perform_later(*args) 
    end 

    private 

    def url_options 
     options = {} 
     request = Thread.current["actiondispatch.request"] 
     if request 
     host  = request.host 
     port  = request.port 
     protocol = request.protocol 
     lang = request.params[:locale_lang] 
     city = request.params[:locale_city] 
     standard_port = request.standard_port 
     options[:protocol] = protocol 
     options[:host]  = host 
     options[:port]  = port if port != standard_port 
     options[:locale_lang] = lang 
     options[:locale_city] = city 
     end 
     ActionMailer::Base.default_url_options.merge(options) 
    end 
    end 

    module DeliveryJobOverrides 
    def perform(mailer, mail_method, delivery_method, url_options, *args) 
     mailer = mailer.constantize 
     mailer.default_url_options = url_options 
     mailer.public_send(mail_method, *args).send(delivery_method) 
    end 
    end 
end 

А затем предварять их к соответствующим классам в инициализаторе