MagicReport
An easy way to export data to CSV
Installation
Add this line to your application’s Gemfile:
gem "magic-report", require: "magic_report"
Getting Started
This gem provides an ActiveRecord-like DSL to create CSV reports. One of the common use cases is when you have nested data.
class User < MagicReport::Report
field :id
field :is_admin, ->(user) { user.is_admin ? "Yes" : "No" }
end
report = User.new
report.process(UserModel.first)
# You can also `process` on a collection
# report.process(User.all.limit(50))
report.as_csv
The example above is basic - you have a User model and you want to export the two fields id
and is_admin
.
The users of your application may not particularly like the naming true
or false
since these are more technical terms, that's why you can pass an additional block to the field.
Also, for each report you must provide locales file:
en:
magic_report:
user:
id: ID
is_admin: Admin?
CSV will be | ID | Admin? | | ---- | -------- | | 123 | Yes | | 222 | No |
Nested
Let's look at a more complex example. Now we have a user model with an address and several cars.
class User < MagicReport::Report
field :id
field :is_admin, ->(user) { user.is_admin ? "Yes" : "No" }
has_one :shipping_address, class: Address, prefix: -> { t("shipping_address") }
has_one :billing_address, class: Address, prefix: -> { t("billing_address") }
has_many :cars, class: Car, prefix: -> { t("car") }
end
class Address < MagicReport::Report
fields :address_line_1, :city
end
class Car < MagicReport::Report
field :name
end
Because we have explicitly said that the user has_many :cars
, the number of lines in the CSV will be equal to the number of cars.
en:
magic_report:
user:
id: ID
is_admin: Admin?
address: User address
cars: Car
shipping_address: Shipping address
billing_address: Billing address
car:
name: Name
address:
address_line_1: Line 1
city: City
CSV will be | ID | Admin? | Shipping address Line 1 | Shipping address City | Billing address Line 1 | Billing address City | Car Name | | ---- | -------- | ------------------- | ----------------- | -------- | -------- | ------- | | 123 | Yes | 5th Ave | NY | Chester st | San Francisco | Lexus | | 123 | Yes | 5th Ave | NY | Chester st | San Francisco | BMW |
Using with blocks
The above example can be rewritten using blocks instead of class
class User < MagicReport::Report
field :id
field :is_admin, ->(user) { user.is_admin ? "Yes" : "No" }
# You should always provide `name` option if you're using block instead of class
# From this option will be used locales for `address_line_1` and `city`
has_one :shipping_address, name: :address, prefix: -> { t("shipping_address") } do
fields :address_line_1, :city
end
# Prefix locale is taken from `user.billing_address`
has_one :billing_address, name: :address, prefix: -> { t("billing_address") } do
fields :address_line_1, :city
end
has_many :cars, name: :car, prefix: -> { t("car") } do
field :name
end
end
Contributing
Everyone is encouraged to help improve this project. Here are a few ways you can help:
- Report bugs
- Fix bugs and submit pull requests
- Write, clarify, or fix documentation
- Suggest or add new features
To get started with development and testing, check out the Contributing Guide.