Carrierwave。仅在保存模型后处理(model.id为nil)

时间:2014-06-17 11:17:56

标签: ruby-on-rails carrierwave

我需要处理代表pdf文件的附件。 但我的处理取决于此时不存在的模型(未保存)。

我需要配置上传器,他只有在保存模型后才开始工作。或类似的东西。

rails 4.0.1,carrierwave 0.10.0

backup_uploader.rb

class BackupUploader < CarrierWave::Uploader::Base
  include RenderAnywhere

  storage :dropbox
  process :render_check

  def store_dir
  end

  def filename
  end

  def extension_white_list
    ["pdf"]
  end

  def render_check
    # To render following pdf, i need fullfilled model
    # Especially model.id

    set_instance_variable("check", model)
    pdf = WickedPdf.new.pdf_from_string(render('checks/check.pdf.erb'),
      wkhtmltopdf: Rails.root.join('bin', 'wkhtmltopdf').to_s,
      zoom: 0.81,
      margin: { top: 18, bottom: 0, left: 0, right: 0 }
    )

    rendered_path = "#{Rails.root}/tmp/#{@check.id}rendered.pdf"

    File.open(rendered_file_path,  "w") { |file| file.write(pdf.force_encoding("UTF-8")) }

    Prawn::Document.merge(self.current_path, [self.full_cache_path, rendered_path ])

  end

  end

chek.rb

class Check < ActiveRecord::Base
  belongs_to :project

  mount_uploader :backup, BackupUploader

end

checks_controller.rb

def create
    @check = current_project.checks.build(check_params)
    respond_to do |format|
      if @check.save
        format.html {}
        format.js {}
      else
        format.html {}
        format.js {}
      end
    end
  end

更新

我有一个解决方案,但我不喜欢它。我认为有更好的方法。

现在如何运作:

chek.rb

class Check < ActiveRecord::Base
  belongs_to :project

  mount_uploader :backup, BackupUploader
  skip_callback :save, :after, :store_backup! # <= Skip storing
end

checks_controller.rb

def create
    @check = current_project.checks.build(check_params)
    backup = @check.backup
    respond_to do |format|
      if @check.save
        StorageWorker.perform_async(@check.id, backup.file.try(:file)) #<= This job perform processing.
        format.html {}
        format.js {}
      else
        format.html {}
        format.js {}
      end
    end
  end

backup_uploader.rb

class BackupUploader < CarrierWave::Uploader::Base

  storage :dropbox

  def store_dir
  end

  def filename
  end

  def extension_white_list
    ["pdf"]
  end


  end

storage_worker.rb

class StorageWorker
  include Sidekiq::Worker
  include RenderAnywhere
  sidekiq_options retry: false

  def perform(check_id, tmp_file_path)
    @check = Check.find(check_id)
    set_instance_variable("check", @check) # Need for rendering check.pdf.erb. See RenderAnywhere gem.
    pdf = WickedPdf.new.pdf_from_string(render('checks/check.pdf.erb'),
      wkhtmltopdf: Rails.root.join('bin', 'wkhtmltopdf').to_s,
      zoom: 0.81,
      margin: { top: 18, bottom: 0, left: 0, right: 0 }
    )

    rendered_file_path = "#{Rails.root}/tmp/#{@check.id}rendered.pdf"
    result_pdf_path = "#{Rails.root}/tmp/#{@check.id}result.pdf"
    pdf_file_paths = [rendered_file_path, tmp_file_path ]

    File.open(rendered_file_path,  "w") { |file| file.write(pdf.force_encoding("UTF-8")) }

    if tmp_file_path.nil?
      result_pdf_path = rendered_file_path
    else
      Prawn::Document.merge(result_pdf_path, pdf_file_paths)
    end

    @check.backup = File.open(result_pdf_path, "r")
    @check.save
    @check.backup.store!


    File.delete(result_pdf_path)
  end

end

0 个答案:

没有答案