我需要处理代表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