Rapport

Rapport allows you to create tabular reports with a DSL, which can be outputted via customizable formatters.

Quick-Start

Include the Rapport::Report module in any object to allow it to generate reports in the pre-built formatters (csv, fake) or in a custom formatter. Use an easy DSL to write all your reports once, and all your formats once, and then mix and match as you please.

Creating a Report

require 'rubygems'
require 'rapport'

class OrderReport
  include Rapport::Report

  def initialize(options)
    self.options = options
  end

  # Add columns to the report with column(column_header, *args)
  # Column Header is what appears in the report, and *args specify how to calculate the values using the model
  #
  #   examples:
  #     column('column header')
  #     column('column header', :column_symbol)
  #     column('column header', :model_type => :column_symbol, ...)
  #
  # All equivalent:
  # column 'Product ID', :map_to => lambda {|model| !model.nil? and model.respond_to?(:product_id) ? model.product_id : nil }
  # column 'Product ID', :map_to => :product_id
  # column 'Product ID', :product_id
  column 'Product ID'         # by default converts 'Product ID' to :product_id

  # special calculation depending on type of model
  column 'Price',         :additional_charge => :amount,
                          :line_item => :price,  # not required; defaults to :price
                          :special_line_item => lambda {|line_item| line_item.price - line_item.tax },
                          # Display price (in cents) as dollars
                          :format => :cents 

  # Navigate an object heirarchy using :through
  column 'Order ID',      :through -> :order, :map_to => :id                    
  column 'Customer Name', :through => [:order, :customer], :map_to => lambda {|customer| "#{customer.first_name} #{customer.last_name}" }

  # Implement each_model to specify which models belong to the report.
  # The method should yield each model, and optionally specify the model type in order to customize how the value is calculated.
  def each_model
    AdditionalCharge.in_order_report.each do |additional_charge|
      yield additional_charge # equivalent to yield additional_charge, :additional_charge
    end

    LineItem.in_order_report.each do |line_item|
      if line_item.special?
        yield line_item, :special_line_item  # uses special price calculation above 
      else
        yield line_item  # equivalent to yield line_item, :line_item
      end
    end
  end
end

Running a Report

order_report = OrderReport.new(:format => 'csv', :output_dir => 'my_dir')
order_report.generate # generates a csv file named 'my_dir/OrderReport_{timestamp}.csv

order_report = OrderReport.new(:format => 'my_custom')
order_report.generate # generates the same report, but in your custom format

Creating a Custom Format

module Rapport
  class ReportGeneratorMyCustom
    include ReportGenerator

    generate_with do |report|
      File.open(output_filename,'w') do |file|
        file.puts(report.column_headers.join('|'))
        report.each_row do |row|
          file.puts(row.join('|'))
        end
      end
    end

  end
end

Copyright (c) 2011 Andrew Wheeler. See LICENSE.txt for further details.