【问题标题】:Using view_context inside the Mailer在 Mailer 中使用 view_context
【发布时间】:2015-05-03 13:07:21
【问题描述】:

我正在使用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 类以生成发票。

结果:电子邮件发送正确

使用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

【问题讨论】:

  • 包含完整的错误跟踪可能很有用。
  • 我已经编辑了这个问题。我没有得到清晰的堆栈跟踪,因为调用是使用 ajax ...
  • github.com/rails/rails/blob/… 解释正在发生的事情。
  • 解决此限制的一种方法是仅将所需的信息作为字符串或整数传递。
  • 为什么需要视图上下文? InvoicPdf 类的外观如何?一种方法是在发送电子邮件之前创建 PDF,或者第二种方法是在 InvoiceMailer 中手动创建 view_context。如果你想使用deliver_later 方法,你绝对不能将它作为参数传递给InvoiceMailer

标签: ruby-on-rails sidekiq rails-activejob


【解决方案1】:

传递一个像视图上下文这样的对象然后使用deliver_later 的问题是你给它的参数被序列化到一些后端(redis、MySQL),而 另一个 ruby​​ 后台进程选择稍后补上。

像视图上下文这样的对象并不是你可以序列化的东西。这不是真正的数据

您可以只使用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 课程中所做的,这可能与您的InvoicePdf 课程相似。

    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

【讨论】:

    猜你喜欢
    • 2022-01-20
    • 2019-08-04
    • 2011-11-26
    • 2014-05-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-02-07
    相关资源
    最近更新 更多