在 rails 邮件程序上调用 deliver_later 之前存储当前可选路由范围
Storing current optional route scope before calling deliver_later on rails mailer
Rails 4.2
Ruby2.3
我有两个可选路由 scopes 与 locale 信息相关。它们设置在配置 default_url_options 方法的 application_controller
中的 before_action
中。即
# 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/ or http://localhost:3000/en/
这一切都在浏览器中按预期工作,但我想利用 ActionMailer::DeliveryJob 在后台进程中发送电子邮件。一个明显的问题是 ActionMailer::DeliveryJob 不存储 params[:locale]
.
的值
我希望能够调用 SomeMailer.generic_email(options).deliver_later
并将当前的 default_url_options
发送到 ActionMailer::DeliveryJob ,然后 ActionMailer::DeliveryJob 将沿着链传递那些并在实际处理时使用它们邮件。我当然可以将 default_url_options 定义为每个 Mailer 方法的参数,但我更愿意设置应用程序以便自动包含它。
您是否遇到过此问题或对如何处理该任务有任何建议。请记住,它也应该是线程安全的。
我目前失败的方法是将当前的请求保存在Thread.current中,然后在enqueue_delivery 通过 .deliver_later 调用。然后我想覆盖 ActionMailer::DeliveryJob 的 perform 方法来接受 url_options 并使用 class_eval 在 current mailer [=76] 中定义 default_url_options 方法=]。 但是,使用时似乎甚至没有调用 perform 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
以防其他人想要这样做。我通过添加
修复了它
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
然后将它们添加到初始值设定项
中的相应 类
Rails 4.2 Ruby2.3
我有两个可选路由 scopes 与 locale 信息相关。它们设置在配置 default_url_options 方法的 application_controller
中的 before_action
中。即
# 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/ or http://localhost:3000/en/
这一切都在浏览器中按预期工作,但我想利用 ActionMailer::DeliveryJob 在后台进程中发送电子邮件。一个明显的问题是 ActionMailer::DeliveryJob 不存储 params[:locale]
.
我希望能够调用 SomeMailer.generic_email(options).deliver_later
并将当前的 default_url_options
发送到 ActionMailer::DeliveryJob ,然后 ActionMailer::DeliveryJob 将沿着链传递那些并在实际处理时使用它们邮件。我当然可以将 default_url_options 定义为每个 Mailer 方法的参数,但我更愿意设置应用程序以便自动包含它。
您是否遇到过此问题或对如何处理该任务有任何建议。请记住,它也应该是线程安全的。
我目前失败的方法是将当前的请求保存在Thread.current中,然后在enqueue_delivery 通过 .deliver_later 调用。然后我想覆盖 ActionMailer::DeliveryJob 的 perform 方法来接受 url_options 并使用 class_eval 在 current mailer [=76] 中定义 default_url_options 方法=]。 但是,使用时似乎甚至没有调用 perform 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
以防其他人想要这样做。我通过添加
修复了它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
然后将它们添加到初始值设定项
中的相应 类