【问题标题】:Can't resolve image into URL: undefined method `polymorphic_url' for #<ActionView::Base无法将图像解析为 URL:#<ActionView::Base 的未定义方法 `polymorphic_url'
【发布时间】:2018-07-04 09:04:03
【问题描述】:

在我的 Rails 应用程序中,我有一个使用 WickedPDF 创建 PDF 文件的工作。在我迁移到 Rails 5.2 之前,这一直很好,现在我收到了这个错误:

ActionView::Template::Error (Can't resolve image into URL: undefined method `polymorphic_url' for #<ActionView::Base:0x0000000004854590>):

发生这种情况的代码是视图中的这一行:

image_tag(image)

这个视图是从 Job 渲染的,我在下面完整添加了它。执行类中的最后一个方法时发生错误:private def render_image_pdf(view, pdf_name, image),它正在呈现 PDF。

回滚到 Rails 5.1 后,一切又正常了,所以我很确定这与 Rails 5.2 中添加/更改的功能有关。那么我应该改变什么才能让它再次工作呢?

PDF 作业:

class SendInvoiceAsAttachmentJob < ApplicationJob
  require 'open-uri'
  queue_as :default

  def perform(target, invoice, send_invoice, to, cc, subject, body1, body2, body3)
    view = ActionView::Base.new(ActionController::Base.view_paths, {})
    view.extend(ApplicationHelper)
    view.extend(Rails.application.routes.url_helpers)

    # Create invoice as PDF
    pdf = Rails.root.join('tmp', "tmp_invoice.pdf")

    File.open(pdf, 'wb') do |file|
      file << render_invoice_pdf(invoice, view, "tmp_invoice.pdf")
    end

    # Add (signed) timesheet as PDF
    projectuser = Projectuser.where(project_id: invoice.project_id, user_id: invoice.user_id).order(:updated_at).last
    if projectuser.blank? or invoice.fixed_price? or invoice.project.service?
      pdf_name = "#{invoice.set_pdf_filename}.pdf"
      pdf_to_email = pdf
    else
      if invoice.timesheet and invoice.timesheet.signed_copy?(projectuser)
        # Download signed copy
        timesheet_copy = TimesheetCopy.where(projectuser_id: projectuser.id, timesheet_id: invoice.timesheet_id).first

        timesheet_file = Rails.root.join('tmp', timesheet_copy.attachment_file_name)
        timesheet_name = timesheet_copy.attachment_file_name

        if timesheet_copy.attachment.url.index("http").blank?
          download = open("https:#{timesheet_copy.attachment.url}")
        else
          download = open(timesheet_copy.attachment.url)
        end
        IO.copy_stream(download, timesheet_file)

        # Push into a PDF when image
        if timesheet_copy.attachment_file_name.index(".pdf") == nil
          timesheet_tmp = Rails.root.join('tmp', "tmp_timesheet.pdf")
          File.open(timesheet_tmp, 'wb') do |file|
            file << render_image_pdf(view, "tmp_timesheet.pdf", timesheet_file)
          end
          timesheet_file = timesheet_tmp
          File.delete Rails.root.join('tmp', timesheet_copy.attachment_file_name)
        end
      else
        # Create timesheet PDF
        timesheet = Timesheet.find(invoice.timesheet_id)
        timesheet_builder = TimesheetBuilder.new(timesheet.month, timesheet.year)

        timesheet_name = "Timesheet #{timesheet.user.full_name} #{I18n.t("date.month_names")[timesheet.month]} #{timesheet.year}"
        timesheet_file = Rails.root.join('tmp', timesheet_name)

        File.open(timesheet_file, 'wb') do |file|
          file << render_timesheet_pdf(timesheet, view, timesheet_name, projectuser, timesheet_builder)
        end
      end

      # Combine the 2 PDF's
      combined_pdf = CombinePDF.new
      combined_pdf << CombinePDF.load(pdf, allow_optional_content: true)
      combined_pdf << CombinePDF.load(timesheet_file, allow_optional_content: true)
      pdf_name = "#{invoice.set_pdf_filename}.pdf"
      combined_pdf.save Rails.root.join('tmp', pdf_name)
      pdf_to_email = Rails.root.join('tmp', pdf_name)

      File.delete(timesheet_file)
    end

    # Send email
    if target == "basecone"
      company = Company.find(invoice.company_id)
      UserMailer.send_pdf_to_basecone(company.basecone_email, pdf_to_email, pdf_name).deliver
    else
      UserMailer.invoice_email(invoice, send_invoice, to, cc, subject, body1, body2, body3, pdf_to_email, pdf_name).deliver
    end

    File.delete(pdf_to_email)
  end

  private def render_invoice_pdf(invoice, view, pdf_name)
    WickedPdf.new.pdf_from_string(
      view.render(
        pdf: pdf_name,
        template: 'admin/invoices/show_as_attachment.pdf.haml',
        locals: { invoice: invoice, copy_invoice: nil },
        print_media_type:  true,
        orientation:       'Portrait',
        page_size:         'A4'
      )
    )
  end

  private def render_timesheet_pdf(timesheet, view, pdf_name, projectuser, timesheet_builder)
    WickedPdf.new.pdf_from_string(
      view.render(
        pdf: pdf_name,
        template: 'timesheets/show_as_attachment.pdf.haml',
        locals: { timesheet: timesheet, timesheet_builder: timesheet_builder, projectuser: projectuser },
        print_media_type:  true,
        orientation:       'Portrait',
        page_size:         'A4'
      )
    )
  end

  private def render_image_pdf(view, pdf_name, image)
    WickedPdf.new.pdf_from_string(
      view.render(
        pdf: pdf_name,
        template: 'admin/invoices/image_timesheet_as_attachment.pdf.haml',
        locals: { image: image },
        print_media_type:  true,
        orientation:       'Portrait',
        page_size:         'A4'
      )
    )
  end
end

【问题讨论】:

  • 你还面临同样的问题吗?

标签: ruby-on-rails


【解决方案1】:

使用wicked_pdf_image_tag 而不是image_tag

<%=wicked_pdf_image_tag image%>

【讨论】:

  • 嗯,这似乎解决了问题,但我想了解原因
  • 不确定,但我遇到了同样的情况。 github.com/mileszs/wicked_pdf/issues/36
  • 查看可能有助于您理解的给定链接。如果对您有帮助,请随时接受 /upvote 答案:)
【解决方案2】:

您可以使用新的ActionController::Renderer API 来执行视图,而不是手动构建 ActionView 设置(因此需要添加所有正确的助手,这是您出错的地方 - 我认为有些移动了)在任意控制器的上下文中渲染。

# Very untested; please treat this is syntactically-valid pseudocode...

WickedPdf.new.pdf_from_string(
  ApplicationController.render(
    template: 'admin/invoices/show_as_attachment.pdf.haml',
    assigns: {
      pdf: pdf_name,
      print_media_type: true,
      orientation: 'Portrait',
      page_size: 'A4',
    },
    locals: { invoice: invoice, copy_invoice: nil },
  )
)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-10-28
    • 2012-08-02
    • 1970-01-01
    • 1970-01-01
    • 2020-06-25
    • 1970-01-01
    • 2010-10-24
    相关资源
    最近更新 更多