在 Mailer 中使用 view_context
Using view_context inside the Mailer
我正在使用 ActiveJob
发送邮件:
使用deliver_now
方法:
invoices_controller.rb
def send_invoice
#other stuff
Members::InvoicesMailer.send_invoice(@invoice.id, view_context).deliver_now
end
invoices_mailer.rb
require 'open-uri'
class Members::InvoicesMailer < ApplicationMailer
def send_invoice(invoice_id, view_context)
@invoice = Invoice.find(invoice_id)
attachments["#{@invoice.identifier}.pdf"] = InvoicePdf.new(@invoice, view_context).render
mail :to => @invoice.client.email, :subject => "Invoice"
end
end
请注意,我将 view_context
从控制器发送到邮件程序,邮件程序将再次将其传递给 InvoicePdf
class 以生成发票。
结果: 邮件发送正确
使用deliver_later
方法:
invoices_controller.rb
def send_invoice
#other stuff
Members::InvoicesMailer.send_invoice(@invoice.id, view_context).deliver_later
end
结果: ActiveJob::SerializationError in Members::InvoicesController#send_invoice Unsupported argument type:
view_context
.
如何将 view_context
注入 InvoicePdf
,从 InvoicePdf
或 InvoiceMailer
中加载?
编辑:这是 InvoicePdf 的样子
invoice_pdf.rb
class InvoicePdf < Prawn::Document
def initialize(invoice, view_context)
@invoice, @view_context = invoice, view_context
generate_pdf
end
def generate_pdf
# calling some active_support helpers:
# @view_context.number_to_currency(//)
# calling some helpers I created
end
end
传递像视图上下文这样的对象然后使用deliver_later
的问题是你给它的参数被序列化到一些后端(redis,MySQL),并且另一个 ruby 后台进程稍后接收它。
像视图上下文这样的对象实际上不是可以序列化的东西。这不是真的 data.
您可以只使用 ActionView::Base.new
,例如 rails console
:
# New ActionView::Base instance
vagrant :002 > view = ActionView::Base.new
# Include some helper classes
vagrant :003 > view.class_eval { include ApplicationHelper }
vagrant :004 > view.class_eval { include Rails.application.routes.url_helpers }
# Now you can run helpers from `ApplicationHelper`
vagrant :005 > view.page_title 'Test'
"Test"
# And from url_helpers
vagrant :006 > view.link_to 'Title', [:admin, :organisations]
=> "<a href=\"/admin/organisations\">Title</a>"
这是我在 PdfMaker
class 中所做的,这可能与您的 InvoicePdf
class.
类似
def action_view
@action_view ||= begin
view = ActionView::Base.new ActionController::Base.view_paths
view.class_eval do
include Rails.application.routes.url_helpers
include ApplicationHelper
include FontAwesome::Rails::IconHelper
include Pundit
def self.helper_method *name; end
def view_context; self; end
def self.before_action f; end
def protect_against_forgery?; end
end
view
end
end
我正在使用 ActiveJob
发送邮件:
使用deliver_now
方法:
invoices_controller.rb
def send_invoice
#other stuff
Members::InvoicesMailer.send_invoice(@invoice.id, view_context).deliver_now
end
invoices_mailer.rb
require 'open-uri'
class Members::InvoicesMailer < ApplicationMailer
def send_invoice(invoice_id, view_context)
@invoice = Invoice.find(invoice_id)
attachments["#{@invoice.identifier}.pdf"] = InvoicePdf.new(@invoice, view_context).render
mail :to => @invoice.client.email, :subject => "Invoice"
end
end
请注意,我将 view_context
从控制器发送到邮件程序,邮件程序将再次将其传递给 InvoicePdf
class 以生成发票。
结果: 邮件发送正确
使用deliver_later
方法:
invoices_controller.rb
def send_invoice
#other stuff
Members::InvoicesMailer.send_invoice(@invoice.id, view_context).deliver_later
end
结果: ActiveJob::SerializationError in Members::InvoicesController#send_invoice Unsupported argument type:
view_context
.
如何将 view_context
注入 InvoicePdf
,从 InvoicePdf
或 InvoiceMailer
中加载?
编辑:这是 InvoicePdf 的样子
invoice_pdf.rb
class InvoicePdf < Prawn::Document
def initialize(invoice, view_context)
@invoice, @view_context = invoice, view_context
generate_pdf
end
def generate_pdf
# calling some active_support helpers:
# @view_context.number_to_currency(//)
# calling some helpers I created
end
end
传递像视图上下文这样的对象然后使用deliver_later
的问题是你给它的参数被序列化到一些后端(redis,MySQL),并且另一个 ruby 后台进程稍后接收它。
像视图上下文这样的对象实际上不是可以序列化的东西。这不是真的 data.
您可以只使用 ActionView::Base.new
,例如 rails console
:
# New ActionView::Base instance
vagrant :002 > view = ActionView::Base.new
# Include some helper classes
vagrant :003 > view.class_eval { include ApplicationHelper }
vagrant :004 > view.class_eval { include Rails.application.routes.url_helpers }
# Now you can run helpers from `ApplicationHelper`
vagrant :005 > view.page_title 'Test'
"Test"
# And from url_helpers
vagrant :006 > view.link_to 'Title', [:admin, :organisations]
=> "<a href=\"/admin/organisations\">Title</a>"
这是我在 PdfMaker
class 中所做的,这可能与您的 InvoicePdf
class.
def action_view
@action_view ||= begin
view = ActionView::Base.new ActionController::Base.view_paths
view.class_eval do
include Rails.application.routes.url_helpers
include ApplicationHelper
include FontAwesome::Rails::IconHelper
include Pundit
def self.helper_method *name; end
def view_context; self; end
def self.before_action f; end
def protect_against_forgery?; end
end
view
end
end