Generating PDF Documents

Problem

You have an application that generates a report, a receipt, or some other output that you'd like users to be able to save. You'd like to generate this output as PDF documents for consistent formatting and convenient distribution.

Solution

Use Ruby FPDF to create PDF documents from within your Rails application.

First, download Ruby FPDF from . Extract the archive, and move the file called fpdf.rb to the your application's lib directory for it to be available to your controllers.

Next, create a Reports Controller that calls require to include the PDF creation library in your lib directory. This controller defines a private method called pdf_report_card and a public method or action called pdf_report.

app/controllers/reports_controller.rb:

class ReportsController < ApplicationController
 require 'fpdf'
 def index
 end
 def pdf_report
 # Data
 col_sizes = [40,20,20,20]
 data = [['Course','Exam 1','Exam 2','Final'],
 ['ENGLISH 101','90','87','B'],
 ['MUSIC 5A','97','100','A'],
 ['CALC 2','98','91','A'],
 ['SWIM','89','84','B'],
 ['HIST 110','91','81','B']]
 send_data pdf_report_card(col_sizes, data),
 :filename => "report.pdf", 
 :type => "application/pdf" 
 end
 private
 def pdf_report_card(col_sizes, data)
 pdf = FPDF.new
 pdf.AddPage
 pdf.SetFont('Arial','B')
 pdf.SetFontSize(10)
 pdf.SetFillColor(50,50,50)
 pdf.SetTextColor(255)
 pdf.SetDrawColor(0)
 pdf.SetLineWidth(0.2)
 # Table Header
 i = 0 
 col_sizes.each do
 pdf.Cell(col_sizes[i],7,data[0][i],1,0,'C',1)
 i += 1
 end
 pdf.Ln()
 pdf.SetFillColor(218,206,255)
 pdf.SetTextColor(0)
 pdf.SetFont('Arial')
 fill = 0
 # Table Data
 data[1..-1].each do |row|
 pdf.Cell(col_sizes[0],6,row[0],'LR',0,'L',fill)
 pdf.Cell(col_sizes[1],6,row[1],'LR',0,'L',fill)
 pdf.Cell(col_sizes[2],6,row[2],'LR',0,'L',fill)
 pdf.Cell(col_sizes[3],6,row[3],'LR',0,'C',fill)
 pdf.Ln()
 fill = (fill-1).abs % 2
 end
 # Bottom Table Border
 total = 0
 col_sizes.each {|x| total += x}
 pdf.Cell(total,0,'','T');
 pdf.Output
 end end

The index.rhtml simply creates a link that generates a PDF report card:

app/views/reports/index.rhtml:

<h1>Report</h1>
<%= link_to 'Make PDF', :action => 'pdf_report' %>

Discussion

The solution displays a 'Make PDF' link. Clicking this link calls the pdf_report action of the Reports Controller when clicked. pdf_report defines an array of four integers that are the column widths of the table to be generated. The actual data to be output is defined as a two-dimensional array and stored in data. The PDF version of the report is returned to the user with the send_data method, which itself calls pdf_report_card to create the PDF. send_data also takes the :filename and :type options, which help browsers render or save the file.

pdf_report_card takes two array arguments; the column widths and a structure of the data to be output. The function creates a new FPDF object and then sets up display properties for the table header, including font and background color. The contents of data is then iterated over, and the body of the table is created. The final call to pdf.Cell draws the bottom border to the table.

shows the solution's PDF output.

Figure 15-2. A PDF containing a list of classes with exam scores

See Also

  • Documentation for Ruby FPDF doesn't exist other than the examples included in the source download. This is because the PHP version of FPDF's documentation is almost completely applicable to Ruby FPDF's API.