An easy way to generate reports in different formats. See example project
class UserOrdersReport < Reporter::Report
# define builder for csv
builder :csv do |report|
data = report.data
csv = CSV.new(StringIO.new)
csv << data.columns
data.rows.each do |row|
css << row
end
csv.to_io
end
# define builder for xlsx
builder :xlsx do |report|
data = report.data
p = Axlsx::Package.new
wb = p.workbook
wb.add_worksheet(name: 'Basic Worksheet') do |sheet|
sheet.add_row(data.columns)
data.rows.each do |row|
sheet.add_row(row)
end
end
p.to_stream
end
# define method which is called in the builders above.
# The name of the method can be any as well as the logic and theirs amount.
# Implementation is all up to you.
def data
query = <<-SQL)
SELECT users.id SUM(orders.amount) AS amount
FROM users LEFT JOIN orders ON users.id = orders.user_id
WHERE created_at >= :start AND created_at <= :end
GROUP BY users.id
SQL
connection.execute(
sanitize_sql_for_assignment([query, start: form_object.start, end: form_object.end])
)
end
end
class UserOrdersXmlBuilder
def call(report)
data = report.data
io = StringIO.new
io.write(data.to_xml)
io
end
end
class UserOrdersReport < Reporter::Report
builder :xml, builder_class: UserOrderXmlBuilder
def data
...
end
end
# form object
class UserOrderForm < Reporter::TimeRangeForm
attribute :user_id, :integer
validate :user_id, presence: true
end
class UserOrdersReport < Reporter::Report
set_form_class UserOrdersForm
end
# app/views/forms
<%= report_form(report) do |form| %>
...
<%= form.fields_for :form, report.form_object do |f|%>
<%= f.select :user_id, User.pluck(:id, :name) %>
<% end %>
...
<%= form.submit class: 'btn btn-primary' %>
<% end %>
By default are using Reporter::BaseForm If you want to override it for scope of you reports you need this:
class UserReportBase < Reporter::Report
default_form_class = UserBaseForm
end
class UserOrdersReport < UserReportBase
# define builders and etc
end
Add this line to your application's Gemfile:
gem "reporter"
And then execute:
$ bundle
Or install it yourself as:
$ gem install reporter
Mount routes:
# config/routes.rb
mount Reporter::Engine => "/reporter"
The gem is available as open source under the terms of the MIT License.