Javascript 在mail in Rails 4中生成PDF作为附件

Javascript 在mail in Rails 4中生成PDF作为附件,javascript,ruby-on-rails,pdfkit,wicked-pdf,shrimp,Javascript,Ruby On Rails,Pdfkit,Wicked Pdf,Shrimp,问题 我想发送附有发票PDF的电子邮件 我已经有了一个带有样式和javascript的invoice show视图 javascript正在计算total字段,格式化货币和日期,并在分页符处拆分 show视图显示发票的方式与pdf上的显示方式相同 尝试 我试了又试。问题是 这样做的时候 html = render_to_string(:action => "../invoices/show_pdf.html.erb") mail(:to => @registration.billi

问题

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

我已经有了一个带有样式和javascript的invoice show视图

javascript正在计算total字段,格式化货币和日期,并在分页符处拆分

show视图显示发票的方式与pdf上的显示方式相同

尝试

  • 我试了又试。问题是 这样做的时候

    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时,它是正确的

  • 我还尝试了使用phantomjs生成 PDF格式。这个解决方案的问题是我正在使用Desive and phantomjs浏览器必须以某种方式登录
  • 我需要一些关于这个问题优雅解决方案的建议

    或者

    在使用pdfkit或wicked_PDF生成PDF之前,使用所有javascript呈现视图的某种方法

    如何将会话cookie分配给phantomjs


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

    我认为
    是你最好的选择。因为您需要执行javascript,所以运行
    PhantomJS
    的解决方案可能是您唯一的选择

    Shrimp提供了一种在请求中添加会话cookie的简单方法。仅限于以下内容:

    Shrimp::Phantom.new(url, options, {user_session: "a session"})
    
    您可以理解,接受选项哈希,然后接受包含cookie及其值的哈希

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


    编辑:添加Andreas关于如何使用Desive在Rails应用程序中破解用户会话的发现,该发现基于Shrimp创建者的相关研究:

    lib/design/sign_in_interceptor.rb

    config/application.rb

    通过此设置,我们可以向资源中添加一个to_pdf方法 发票.rb


    我试着编辑你的答案来合并我的答案,但是编辑被拒绝了,因为“这个编辑在原来的帖子中改变太多了;帖子的原始意思或意图将丢失。”作为将来的参考,当我们只需要一个答案时,我真的不喜欢两个答案。在你的答案中编辑我的答案,我会接受你的答案。我在上面添加了你的发现。然而,博客链接似乎返回404。我希望这只是暂时的,这是不正确的。我已经修复了它,但仍然是404,可能是因为某种原因网站关闭了。让我们把链接保留几天
    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
    
    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" }
    
    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