Ruport06 Jan 2007
NOTE: THIS GUIDE IS FOR RUPORT 0.7. AND IT IS NOW OUT OF DATE.
There is an updated version of this article available on the official ruport website.
Ruport is a lightweight reporting framework for Ruby. It’s focus is on providing a structure for your report definitions, not on providing a high level language to build the layout of your reports. This means that there are no methods for adding a heading, table or graph to the your report. The developers feel it is important for users of the framework to have flexibility in choosing an output format (pdf, text, html, jpg, svg, smoke signals), and wrapping all those formats with higher level functions is a significant challenge that hasn’t yet been solved.
There are 3 stages to report that Ruport can handle - collecting data, manipulating data and formatting reports. All three steps can be used independently, and in this article I’m focusing exclusively on the formatting reports - I’ll leave working with data for another day.
Ruport 0.7 was released on 25th December 2006, and with it came a brand new system of defining output formats. This article is intended to be an introduction to using this new system.
As a contrived example, I will run through the definition and use of a report listing book sales for the month of December. All code and sample output is available to download at the end of the article. If at the end you have any questions, feel free to contact me.
Ruport is available as a gem, and assuming you have the rubygems library installed, can be installed using this command:
gem install ruport
If prompted, accept any extra required dependencies.
Generally, each report is made up of at 2 or more classes - 1 for the definition, and 1 for each desired output format. I recommend all these classes are kept in the same file for manageability.
The first class defines the report and the data required to build it - it is important that keep this data as format independent as possible. For our sales report, something like this might be appropriate:
This defines the following facts about our sales report:
- There are 4 stages required to build the report: a header, a body, a footer and finalizing (rendering).
- There are 2 pieces of data required to build the report: a list of titles and a report title. You can define as many options like this as you wish.
On it’s own, the report definition listed above won’t do much - we need to tell ruport how to render it into the required format.
To begin with, we will create a text version of the report. Something like the following placed immediately after the first class should work nicely:
The first line of this class registers this output format with our report definition - this allows us to define as many different output formats for each report as we wish.
The pad function is a simple formatting function to simplify our work with strings.
The next 3 functions are called to build the report. Notice the function names follow a particular style - these names are important and are a direct result of the “build” line in our first class and will be called in the order we specified in the definition.
The finalize function is also named to match the “finalize” line in the report definition, and returns the entire report.
Now that our report is defined with at least 1 output format, we can use it in our application. One important thing to point out is that although Ruport contains it’s own Array-like class that makes managing your data easier, I haven’t used it in this example. Ruport’s Table class would be perfect for storing our book sales data, however I wanted to focus on building your report. Maybe next time.
Assuming the report definition is in a file called salesreport.rb, the following code should be placed in app.rb in the same directory:
Once the sample data has been built, the report itself is generated with a single block. Using this approach, building the report within your app is limited to a few simple lines, hiding all formatting complexity.
Sure text is fine in many situations (ie. emailing the report to a co-worker), but these days PDF is becoming the format of choice for many people. How do we add it as an option for our sales report?
As mentioned earlier, Ruport won’t try to abstract any of the complexities of formatting your report. The default library for generating PDFs in Ruport is PDF:Writer, and you will need to get your hands dirty with the foibles of this library to make your PDF. The following code placed inside salesreport.rb should get you started.
The structure of this basically the same as the one that defined the text version, with 2 critical differences:
- It extends Ruport PDF formatting class, which provides and instance of PDF:Writer as pdf_writer
- The class registers itself to our SalesRreport class with a different format (:pdf)
So what changes do we have to make to our application to generate the pdf instead? Leave the sample data definition the same, just modify the remaining lines like so:
- call render_pdf instead of render_txt
- modify the text variable name for readability
- save the file with a pdf extension.
Switching output format’s within your app according to user preference or whatever would be a piece of cake.