Ruby on rails 卡里尔瓦夫。仅在保存模型后处理(model.id为nil)
我需要处理代表提交的pdf文件的附件。 但我的处理取决于此时不存在的模型(未保存) 我需要配置上传,他开始工作后,才模型保存。或者类似的 轨道4.0.1,托架0.10.0 backup\u uploader.rbRuby on rails 卡里尔瓦夫。仅在保存模型后处理(model.id为nil),ruby-on-rails,carrierwave,Ruby On Rails,Carrierwave,我需要处理代表提交的pdf文件的附件。 但我的处理取决于此时不存在的模型(未保存) 我需要配置上传,他开始工作后,才模型保存。或者类似的 轨道4.0.1,托架0.10.0 backup\u uploader.rb class BackupUploader < CarrierWave::Uploader::Base include RenderAnywhere storage :dropbox process :render_check def store_dir e
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
class Check < ActiveRecord::Base
belongs_to :project
mount_uploader :backup, BackupUploader
end
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
class Check < ActiveRecord::Base
belongs_to :project
mount_uploader :backup, BackupUploader
skip_callback :save, :after, :store_backup! # <= Skip storing
end
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
class BackupUploader < CarrierWave::Uploader::Base
storage :dropbox
def store_dir
end
def filename
end
def extension_white_list
["pdf"]
end
end
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
更新:
我有一个解决办法,但我不喜欢。我认为有更好的办法
它现在的工作原理:
chek.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
class Check < ActiveRecord::Base
belongs_to :project
mount_uploader :backup, BackupUploader
end
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
class Check < ActiveRecord::Base
belongs_to :project
mount_uploader :backup, BackupUploader
skip_callback :save, :after, :store_backup! # <= Skip storing
end
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
class BackupUploader < CarrierWave::Uploader::Base
storage :dropbox
def store_dir
end
def filename
end
def extension_white_list
["pdf"]
end
end
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
您在附加之前生成了一个pdf,并且在“上载”它之前需要一个临时文件,对吗?为什么不使用
TempFile
,让CarrierWave正确命名文件?我有两个pdf文件。其中一个由用户附加,另一个由我生成。此后,我将两个文件合并到一个文件中。问题是渲染取决于模型。我在这里看不到任何问题。生成的pdf文件名的相关性是什么?您将它与给定的一个合并。是否需要“保留”添加的部件?文件名不重要。它可以改变。不需要原始文件。我只需要一个合并的文件。