Ruby Report
A simple report generator
Installation
Add this line to your application's Gemfile:
gem "ruby_report"
gem "caxlsx" # optional: for generate xlsx
And then execute:
bundle install
Usage
Create class
class UserReport < RubyReport::Report
columns :name, :age, :role, :created_at
end
Initialize object with data
# data is ActiveRecords or array of objects
report = UserReport.new(data: User.all)
Generate report
# Hash
report.to_h # {header: ["Name", "Age", "Role"], rows: [["Sasha", 18, "Student"]]}
# CSV
report.to_csv # IOString
# XLSX
report.to_xlsx(worksheet_name: "Worksheet") # IOString
Details
Get header
report.header # ["Name", "Age", "Role"]
Default translates for header get from i18n
I18n.t("ruby_reports.#{report.class.name.underscore}.headers.#{key}")
Determine custom header
UserReport.new(data: data, header_builder: ->(key, _report) { "Custom #{key}" })
Get rows
report.rows # [["Sasha", 18, "Student"], ["Jack", 30, "Worker"]]
Select columns
report = UserReport.new(data: data, columns: [:name, :age])
report.headers #["Name", "Age"]
report.rows #[["Sasha", 18], ["Jack", 30]]
Custom row
UserReport.new(data: data, row_resolver: ->(row) { row.user })
Custom row builder
UserReport.new(data: data, row_builder: ->(_row, _key, _report) { "" })
Decorators
class UserDecorator < RubyReport::Decorator
def role
I18n.t("roles.#{object.role}")
end
end
class UserReport < RubyReport::Report
columns :name, :age, :role, decorators: [UserDecorator]
end
Formatters
class TimeFormatter < RubyReport::Formatter
def format(value)
return value unless [::Time, ActiveSupport::TimeWithZone].include?(value.class)
value.utc.to_formatted_s(:report)
end
end
class UserReport < RubyReport::Report
columns :name, :age, :role, :created_at, formatters: [TimeFormatter]
end
Decorator and Formatter with scope
class UserDecorator < RubyReport::Decorator
def role
I18n.t("roles.#{object.role}", account_name: scope[:account].name)
end
end
report = UserReport.new(data: users, scope: {account: account})
Append/prepend other reports
class AccountReport < RubyReport::Report
columns :name
end
class AddressReport < RubyReport::Report
columns :street
end
user_report.prepend_report(account_report)
user_report.add_report(address_report)
XLSX with any worksheets
require "ruby_report/generator/xlsx"
generator = RubyReport::Generator::Xlsx.new
generator.add_report(report, worksheet_name: "Worksheet 1")
generator.add_report(other_report, worksheet_name: "Worksheet 2")
generator.generate # IOString