[Rails] 10分鐘內使用HTML模板產生PDF
[Rails] 10分鐘內使用HTML模板產生PDF
原文出處 How to Generate PDFs with HTML templates in 10 minutes with Rails
前言
為您的Web程式產生PDF並非你想像中的那麼困難。
有很多方法可以做到這一點,還有另一個好用gem,叫做Prawn,但是為了今天的教學,我將介紹另一個流行的gem,叫做wicked_pdf。
WickedPDF使用wkhtmltopdf,它允許您直接從HTML產生PDF,而不必遵守DSL。
此方式能夠更快速的達到想要的效果。
安裝步驟
Step 1: 安裝 wkhtmltopdf 和 wicked_pdf gem
# [path] gemfile
gem 'wicked_pdf'
gem 'wkhtmltopdf-binary'
Step 2: 執行 Generator
rails generate wicked_pdf
接下來,假設你不是透過Gemfile安裝wkhtmltopdf的binary檔案,你需要確保wicked_pdf知道在哪裡找到它們。
# [path] config/initializers/wicked_pdf.rb
WickedPdf.config = {
#:wkhtmltopdf => '/usr/local/bin/wkhtmltopdf',
#:layout => "pdf.html",
#:exe_path => '/usr/local/bin/wkhtmltopdf'
}
如果你沒有寫清楚,你可能會得到一個“Bad wkhtmltopdf’s path”的錯誤訊息。
OK你已經準備好了!現在有2個方式可以使用wicked_pdf。
- 從controller render。
- 從自建的library render。
< I > 從controller render
要使用它從controller呈現pdf,您需要做的是在controller方法中新增以下內容。
讓我們以發票應用為例,當用戶訪問/invoices/1
時,您想產生一份pdf發票。
首先,將以下程式新增到invoices_controller.rb (或使用其他controller)
我會解釋一下每個參數是什麼意思,但請記住將它們替換為您自己的相關數據!
# [path] invoices_controller.rb
def show
@invoice = Invoice.find params[:id]
respond_to do |format|
format.pdf do
render pdf: "file_name_of_your_choice",
template: "invoices/show.pdf.erb",
locals: {:invoice => @invoice}
end
end
end
pdf: “file_name_of_your_choice” 這行表示即將輸出的pdf名稱
template: “invoices/show.pdf.erb” 這行表示使用views/invoices/show.pdf.erb當作模板
locals: {:invoice => @invoice} 這行表示將把@invoice傳入模板中
那麼什麼是invoices/show.pdf.erb
?
<!-- [path] show.pdf.erb -->
<!-- app/views/invoices/show.pdf.erb -->
<h1><%= invoice.title %></h1>
<p><%= invoice.description %></p>
<p><%= invoice.amount %></p>
就像一般的htm.erb一樣,你可以使用pdf.erb,它會把它渲染到你的pdf。
如果您注意到上述程式碼,我們增加了本地參數。就像渲染部分一樣,這將允許您在view中使用您的變數。
這就是全部了。當用戶訪問/invoices/1時,就會產出一個pdf。
< II >從自建的library render
可能有些情況下您想要取得pdf代碼。你不一定要用它作為view的替代顯示。
在這種情況下,您將需要外部渲染您的pdf。
例如,讓我說我有一個外部庫將生成PDF,我想使用生成的PDF作為電子郵件附件。
我們該怎麼做?
首先,讓我們創建一個庫和一個類的方法。
# /lib/pdf_generator/bot.rb
module PdfGenerator
class Bot
def self.receipt(payment_details)
end
end
end
好的,現在可以增加程式碼。
所以,如果你在前面的例子中注意到,我們正在使用 ActionController render PDF:…。
# invoices_controller.rb
def show
..
render pdf: "file_name_of_your_choice",
..
end
該PDF PARAMS是非常重要的。這告訴Rails應用程序使用WickedPDF的渲染方法來解析和創建PDF。
問題是,你不能調用ActionController外的渲染,那麼我們如何從外部的圖形庫渲染?
很簡單,我們把ActionController帶出來並使用render_to_string方法
# in bot.rb
..
class Bot
def self.receipt(payment_details)
# 先宣告一個ActionController
ac = ActionController::Base.new
# 然後,我們可以複製之前的範例的輸出方式。
pdf = ac.render_to_string pdf: "file_name_of_your_choice",
template: "invoices/show.pdf.erb",
locals: {:myvariable => variable}
end
end
..
進階說明 如果想要使用Application Helpers, 你可能會發現你的helpers無法在你的templates中使用。 解決方式,請以ApplicationController.new取代ActionController::Base.new。這樣就可以了!
但等等,這不是只是一個字串嗎?字串有多有用?
那麼現在你可以建立一個臨時文件來存儲pdf。
# in bot.rb
..
pdf = ac.render_to_string pdf: "file_name_of_your_choice",
template: "invoices/show.pdf.erb",
locals: {:myvariable => variable}
# lets create a Tempfile which we will use to generate an actual file to be
# attached to an e-mail
tempfile = Tempfile.new "anynamehere.pdf"
tempfile.binmode
tempfile.write pdf
tempfile.close
tempfile
..
所以現在PdfGenerator::Bot.receipt接收一個對象,將其解析成一個視圖,並返回產生一個漂亮的臨時文件PDF。
使用該tempfile,您可以附加到郵件程式中。
例如:
# example_mailer.rb
def payment_details(details)
attachments["anyfilenametoo.pdf"] = File.read(PdfGenerator::Bot.receipt(details).path)
mail(subject: .....)
end
希望這可以幫助到大家!
參考
- http://dchua.com/2014/10/30/generate-pdfs-with-html-templates-in-rails/
留言