An ActiveRecord plugin that helps to denormalize your existing ActiveRecord models.
It provides an easier way to denormalize/flatten normalized records, and generation the table schema.
Example
Existing normalized tables
orders | customers | line_items |
---|---|---|
id | id | id |
customer_id | name | description |
discount | total | |
total | order_id |
Denormalized table, generated by flatten_record
denormalized_orders |
---|
id |
order_id |
discount |
total |
customer_id |
customer_name |
line_item_id |
line_item_description |
line_item_total |
line_items_sum (custom column) |
total_in_usd (custom column) |
Usage
Add gem dependency
gem 'flatten_record'
Include module in your newly defined model
include FlattenRecord::Flattener
Define denormalization
class DenormalizedOrder < ActiveRecord::Base
include FlattenRecord::Flattener
denormalize :order, {
# specifying association
include: {
# :belongs_to association
customer: {}
# :has_many association, create multiple denormalized records
line_items: {}
},
# save results of methods defined in Normalized model
methods: {
total_in_usd: :decimal
},
# compute results of methods defined in Denormalized model
compute: {
line_items_sum: { type: :decimal, default: 0 }
}
}
private
def compute_line_items_sum(order)
order.line_items.collect(&:total).inject(:+)
end
end
class Order < ActiveRecord::Base
def total_in_usd
# calculation
end
end
Generate migration file
Generate migration file based on the definition
$ rails generate flatten_record:migration denormalized_order
create db/migrate/20140313034700_create_table_denormalized_orders.rb
Update definition and generate new migration file
$ rails generate flatten_record:migration denormalized_order
Warning. Table already exists: denormalized_orders
Generating migration based on the difference..
Add columns: line_items_description
create db/migrate/20140313034736_add_line_items_description_to_denormalized_orders.rb
Use denormalizer methods
Create record
irb(main)> DenormalizedOrder.create_with(order)
Deleting record(s)
irb(main)> DenormalizedOrder.destroy_with(order)
Update record(s)
irb(main)> DenormalizedOrder.update_with(order)
API Documentation/Development/Discussion
Refer to the wiki.
Versions
#####v1
- tree-based denormalization: nicer code & structure √
- new DSL + syntax √
(Credit to @scottharvey's issue #6) - added :prefix option - use your own column prefix √
- added :methods option - save normalized model's method √
(Credit to @scottharvey's idea) - change to old :save option to :compute option √
(Credit to @scottharvey's idea) - deprecate observer √
#####v0
- denormalize fields and nested fields √
- denormalize belongs_to, has_many typed associations √
- generate migration from denormalized model √
- observe model changes and update denormalized model √
Contributors
License
see MIT-LICENSE.