Ruport’s Report class is meant to provide a high level interface to some of Ruport’s core libraries and utilities.
Report provides easy ways to work with Ruport::Query and Ruport::Mailer, and also provides rendering shortcuts. These features make it easier to tie together some of Ruport’s lower level bits into a single object.
Report uses simple hooks to make it act like a Controller object. The following code is an example of rendering tables:
class MyReport < Ruport::Report
renders_as_table
attr_accessor :file
def renderable_data(format)
t = Table(file)
t.sub_table { |r| r.a == "foo" }
end
end
MyReport.generate do |report|
report.file = "in.csv"
report.save_as "out.csv" # renders to csv
report.save_as "out.pdf" # renders to pdf
puts report.to_text # renders to screen as text
end
The other default controllers are also supported, named renders_as_row, renders_as_group, and renders_as_grouping. The data returned by renderable_data(format) will be passed to the controller you specify.
You can also pass default options to your controller if needed, e.g.
renders_as_table :show_table_headers => false
Most interesting Ruport applications make use of custom controllers. It is trivial to make use of them with your reports:
class MyReport < Ruport::Report
renders_with MyCustomController
def renderable_data(format)
# the return of this will be passed as :data to MyCustomController
end
end
You can then continue to use as(), save_as(), and the to_format shortcuts.
For the save_as() function, the follow mappings are used:
save_as("foo.txt") forwards to as(:text)
save_as("foo.pdf") forwards to as(:pdf) and writes as a binary
save_as("foo.csv") forwards to as(:csv)
save_as("foo.html") forwards to as(:html)
For other extensions, if your controller handles them you can still use save_as(), it will just convert the extension to a symbol and pass it to as().
Example: save_as(“foo.xml”) forwards to as(:xml)
These formats will be written using text mode by default, rather than binary. You can specify file access flags if needed, e.g.
save_as("foo.jpg", :flags => "wb")
The following example shows a report which sets up a number of database sources and then generates grouped output. query() is a shortcut interface to Ruport::Query, covering the most common needs.
class MyReport < Ruport::Report
renders_as_grouping
attr_accessor :source
def prepare
add_source :legacy, :dsn => "dbi:mysql:old_db", :user => :root
add_source :default, :dsn => "dbi:mysql:new_db", :user => :root
end
def renderable_data(format)
results = query "select name, email from foo where num < 10",
:source => source
Grouping(results,:by => "name")
end
end
legacy_report = MyReport.new
legacy_report.source = :legacy
legacy_report.save_as "foo.csv"
new_report = MyReport.new # will use :default source
new_report.save_as "bar.csv"
Report offers an alternate interface to Ruport::Mailer. This allows you to easily attach reports to an email and send them via SMTP.
The following example is for using the Report class directly, but would work for subclasses as well.
r = Ruport::Report.new
r.add_mailer :default,
:host => "mail.adelphia.net",
:address => "gregory.t.brown@gmail.com"
r.send_to("gregory.t.brown@gmail.com") do |mail|
mail.subject = "Hello"
mail.attach "foo.csv"
mail.text = "This is an email with attached csv"
end
This information is covered in more detail in the rope cheatsheet, but the
following notes are provided as a quick reference.
rake build report=my_report
rake run report=my_report
If you’d like to share sources between reports, define them in config/environment.rb.
To generate the controller definition:
rake build controller=my_controller
In your report, add require “lib/controllers” and the call:
renders_with MyController
In the ruport-util package there is a tool called ReportManager that allows you to select different reports programatically. This might be useful in web applications, where you’d like to determine which class should generate a report via a drop down menu.
The following simple example shows how this might be used:
class Mars < Ruport::Report
acts_as_managed_report
renders_as_table
def renderable_data(format)
Table("mars.csv")
end
end
class Venus < Ruport::Report
acts_as_managed_report
renders_as_table
def renderable_data(format)
Table("venus.csv")
end
end
["Mars","Venus"].each do |n|
Ruport::ReportManager[n].generate { |r| r.save_as "#{n}.pdf" }
end
Typically, it might be easier to just store report instances in a hash lookup, but there are certain cases where you’ll want to be able to dynamically register and run reports, which is easy to do with ReportManager.
If you need to override the name of a report, add a name method to it which returns a string to identify the report with.
Report is really most useful when used in conjunction with rope, so you’ll want to review that cheatsheet. (See rope cheatsheet.)
Also, much of the heavy lifting can and should be done by your controllers, especially using the various hooks available in them. This class is among the feature sets in the ruport-util package that is likely to change over time to adapt to people’s needs.