Rails3'te, modellerimden birinin bir PDF biçimini oluşturmak için WickedPDF gem
kullanıyorum. Bu iyi çalışıyor: /invoices/123
HTML döndürür, /invoices/123.pdf
bir PDF indirir.Carrierwave aracılığıyla ek için WickedPDF'den PDF alınıyor
Fatura modelimde, Fatura durumunu takip etmek için state_machine gemini kullanıyorum. Bir fatura "faturalandırılmamış" durumundan "faturalandırılan" duruma geçtiğinde, fatura PDF'sinin bir kopyasını almak ve CarrierWave'i kullanarak fatura modeline eklemek isterim.
Üç bölümden ayrı olarak çalışıyorum: denetleyici bir PDF görünümü oluşturur, model doğru geçişi yaparken durumu izler ve geri çağrıyı tetikler ve CarrierWave düzgün şekilde kurulur. Ancak, birlikte güzelce oynamasını sağlayan bir zaman geçiriyorum.
Faturanın HTML sürümünü almak istedim, modelden render_to_string
'u arayabilirim. Ancak render_to_string
, bir PDF ikili dosyası almayı tercih ediyor gibi görünüyor. Bir veri akışı elde edebilirsem, bu verileri bir temp dosyasına yazmak ve yükleyiciye eklemek oldukça kolaydır, ancak veri akışını nasıl alacağımı anlayamıyorum.
Herhangi bir düşünce? Aşağıdaki kodu:
Fatura kontrolörü
def show
@invoice = @agg_class.find(params[:id])
respond_to do |format|
format.pdf do
render_pdf
end
format.html # show.html.erb
format.json { render json: @aggregation }
end
end
...
def render_pdf(options = {})
options[:pdf] = pdf_filename
options[:layout] = 'pdf.html'
options[:page_size] = 'Letter'
options[:wkhtmltopdf] = '/usr/local/bin/wkhtmltopdf'
options[:margin] = {
:top => '0.5in',
:bottom => '1in',
:left => '0in',
:right => '0in'
}
options[:footer] = {
:html => {
:template => 'aggregations/footer.pdf.haml',
:layout => false,
}
}
options[:header] = {
:html => {
:template => 'aggregations/header.pdf.haml',
:layout => false,
}
}
render options
end
Invoice.rb
def create_pdf_copy
# This does not work.
pdf_file = ApplicationController.new.render_to_string(
:action => 'aggregations/show',
:format => :pdf,
:locals => {
:invoice => self
}
)
# This part works fine if the above works.
unless pdf_file.blank?
self.uploads.clear
self.uploads.create(:fileinfo => File.new(pdf_file), :job_id => self.job.id)
end
end
GÜNCELLEME bir çözüm bulundu.
def create_pdf_copy
wicked = WickedPdf.new
# Make a PDF in memory
pdf_file = wicked.pdf_from_string(
ActionController::Base.new().render_to_string(
:template => 'aggregations/show.pdf.haml',
:layout => 'layouts/pdf.html.haml',
:locals => {
:aggregation => self
}
),
:pdf => "#{self.type}-#{self}",
:layout => 'pdf.html',
:page_size => 'Letter',
:wkhtmltopdf => '/usr/local/bin/wkhtmltopdf',
:margin => {
:top => '0.5in',
:bottom => '1in',
:left => '0in',
:right => '0in'
},
:footer => {
:content => ActionController::Base.new().render_to_string({
:template => 'aggregations/footer.pdf.haml',
:layout => false
})
},
:header => {
:content => ActionController::Base.new().render_to_string({
:template => 'aggregations/header.pdf.haml',
:layout => false
})
}
)
# Write it to tempfile
tempfile = Tempfile.new(['invoice', '.pdf'], Rails.root.join('tmp'))
tempfile.binmode
tempfile.write pdf_file
tempfile.close
# Attach that tempfile to the invoice
unless pdf_file.blank?
self.uploads.clear
self.uploads.create(:fileinfo => File.open(tempfile.path), :job_id => self.job.id)
tempfile.unlink
end
end
Tamam, çalışıyorum. Adım 1, bir denetleyici bağlamında çalışmadığında, WickedPDF'nin global yapılandırma ayarlarını yok sayarken çalışmaktadır. Adım 2: PDF çıktısını bir ikili mod tempfile olarak kaydetmek için Tempfile'ı kullanın, ardından bunu Carrierwave'a ekleyin. Çözümü yansıtacak orijinal yayın düzenlendi. – lascarides
Lütfen 1. adımda daha fazla bilgi verebilir misiniz? Yerel olarak wkhtmltopdf eski bir sürümü vardı ve render_to_string ile sadece güzel ihraç ediyordum. Sunucumda wkhtmltopdf 0.11.0 var ve render_to_string çalışıyor ancak PDF okunamıyor .. 0.11.0 lokalize ve render_to_string borazanlarına yükseltildi .. Aynı probleminiz var gibi görünüyor .. FYI: 'file = StringIO kullanıyorum (render_to_string (options)) 'bu yüzden Temp dosyasını atlayabilirim. Bu, ataş ile birlikte, ancak bu fikri beğenirseniz bir deneyebilirsiniz. –
Bunu çözdüğüne sevindim. Çözümünüzü bir cevap olarak yazmalı ve cevabınızı kabul etmelisiniz. Kendi sorunuzu cevaplarken hiçbir zararı yok! – sockmonk