Satya's blog - Making PDFs with JasperReports and Rails 1

Feb 21 2009 18:15 Making PDFs with JasperReports and Rails 1

Here's part 1 of how to produce a nice PDF in a Ruby on Rails application using JasperReports, a Java code library.

Overview:

The development:

  • Set up your Rails application to produce XML for the data to be filled into the template.
  • Make the PDF template using iReport. iReport produces a .jasper file.

The execution:

  • Your Rails application produces XML.
  • A small Java program puts the XML and the template together using the JasperReports libraries. It returns the PDF.
  • Your Rails application accepts the PDF and stores or serves it.

Setting up the template and building the XML should usually be done at the same time. Since I'm not doing a full tutorial on JasprReports, I'll cover things briefly and without screenshots. I'll mostly cover the stuff that's specific to using an XML data source.

First, get your Rails app to somehow return an XML file. Stick a method in the model to build the xml, call the method something like build_xml(). This will take a list of ids of the records that you want in the PDF. I give it a list of ids or an array of grade report data structures because I usually produce a grade report for a given student. By giving this method multiple student ids or data structures, I can produce a whole set of reports in a single PDF file.

By giving it an array of data, each element being one student's grade data, the caller is agreeing to fetch the data from the database. By giving it ids, the builder methods will fetch the data as well as building XML. I do something like this: I put a method in Student class to get the data, and I call that method, and send what it returns to build_xml.

def self.build_xml(grades)
    buffer=""
    xm=Builder::XmlMarkup.new()
    xm.instruct! 
    buffer += xm.grades do
        grades.each do |c|
            build_single_xml(xm, c)
        end
    end
    return buffer
end

build_xml declares a buffer where the XML data will accumulate. xm is the builder object. instruct! puts in the declaration that this is an XML document. xm.grades produces a "grades" XML element, and the block inside it produces the contents of that element. We loop over the array of "grades", calling build_single_xml for each. build_single_xml builds each student's grade report data. So, our XML is going to look like:

<grades>
    <student id="">
        ...data...
    </student>
    ...repeat for each student...
</grades>

Notice that each student's id is included as an attribute.

I won't cover how to generate all the XML at this point. Let's turn to the JasperReports template... in part2.

Tag: geeky rails howto