首页 文章

在Rails 4中生成PDF作为邮件中的附件

提问于
浏览
1

The problem

我想发送附有发票PDF的电子邮件 .

我已经有了发票显示视图,带有样式和javascript .

javascript正在计算总字段,格式化货币和日期以及分页符时分割 .

show view显示的发票就像它应该在pdf上一样 .

Attempts

html = render_to_string(:action => "../invoices/show_pdf.html.erb") 
mail(:to => @registration.billing_email, :subject => "Faktura") do |format|
  format.pdf do
    attachments['faktura.pdf'] = PDFKit.new(html).to_pdf
  end

..我没有浏览器来解释javascript . 所以所有的计算和格式都消失了 . 当我在浏览器中打开pdf时,它是正确的 .

  • 我也试过shrimp,它使用phantomjs来生成PDF . 这个解决方案的问题是我正在使用设计,并且phantomjs浏览器必须以某种方式登录 .

我需要一些关于这个问题的优雅解决方案的建议 .

在使用pdfkit或wicked_pdf生成PDF之前,使用所有javascript呈现视图的一些方法

要么

如何为phantomjs分配会话cookie?

我知道这是两个问题,但是因为它解决了一个问题,我希望它没问题 .

1 回答

  • 3

    我认为 shrimp 是你最好的选择 . 由于您需要执行javascript,因此运行 PhantomJS 的解决方案可能是唯一可行的方法 .

    Shrimp提供了一种在请求中添加会话cookie的简便方法 . 就像下面这样的东西:

    Shrimp::Phantom.new(url, options, {user_session: "a session"})
    

    正如您所理解的那样initializer接受一个选项哈希,然后是一个带有您的cookie及其值的哈希值 .

    现在困难的部分是在服务器上始终有一个有效的会话来执行请求 . 根据您的会话管理(例如,您可能有自动过期),这可能有点棘手 .


    EDIT: 添加Andreas关于如何使用基于Shrimp创建者的相关blog post的Devise来破解Rails应用程序中的用户会话的发现:

    LIB /色器件/ sign_in_interceptor.rb

    module Devise
      class SignInInterceptor
        def initialize(app, opts)
          @app    = app
          @scope  =opts[:scope]
          @secret = opts[:secret]
          @klass  = opts[:klass]
        end
    
        def call(env)
          if user = Rack::Request.new(env).cookies[@secret]
            env['warden'].session_serializer.store(@klass.constantize.find(user), @scope)
          end
    
          @app.call(env)
        end
      end
    end
    

    配置/ application.rb中

    require File.expand_path('../../lib/devise/sign_in_interceptor', __FILE__)
    config.middleware.use Devise::SignInInterceptor, { :scope  => :user, :klass => 'User',
                                                        :secret => "our_very_very_long_secret" }
    

    通过此设置,我们可以将to_pdf方法添加到资源invoice.rb中

    def to_pdf
      host        = Rails.env.production? ? 'www.adjust.io' : 'localhost:3000'
      url         = Rails.application.routes.url_helpers.reports_url(self, :host => host)
      cookie      = { 'our_very_very_long_secret' => user_id } #user_id is a instance method on the invoice class 
      options     = { :margin => "1cm"}
      res         = Shrimp::Phantom.new(url, options, cookie).to_pdf("#{Rails.root}/invoices/invoice_#{self.id}.pdf")
    end
    

相关问题