Is there a way to easily and efficiently fetch the corresponding (child) models of a parent model and then render it in a template? I would like to know how to do it with and without joins
For Example, Consider these 3 tables:
# ProductGroup is the highest parent
class ProductGroup < ActiveRecord::Base
attr_accessible :name, :merchant_id
has_many :product_items
has_many :product_group_selections
end
# ProductItem is a child of ProductGroup
class ProductItem < ActiveRecord::Base
attr_accessible :base_price, :name, :product_group_id
belongs_to :product_group
end
# ProductGroupSelection is a child of ProductGroup
class ProductGroupSelection < ActiveRecord::Base
attr_accessible :name, :price_extra, :product_attr_group_id, :product_item_id
belongs_to :product_group
has_many :product_group_selection_attrs
end
# ProductGroupSelectionAttr is a child of ProductGroupSelection
class ProductGroupSelectionAttr < ActiveRecord::Base
attr_accessible :name, :product_group_id
belongs_to :product_group_selection
end
What I want is a data-structure that looks like this (when searching product_groups for merchant_id = 1)
merchant_id 1 => {
ProductGroup.name, ProductGroup.merchant_id,
ProductItems => [...],
ProductGroupSelections => {ProductGroupSelections.name, ProductGroupSelectionAttrs => [...]}
}
This way I can loop through, in-turn, all groups and their sub models to generate a form using ERB.
Thank you
When iterating over a collection of records that in turn have collections you’ll run into the infamous N+1 query. Essentially for every ProductGroup you would run a query to pull back all of it’s ProductItem records. And worse if your working with 2 levels of relations.
To make this work more efficiently you want to make use of includes which ActiveRecord defines as a means of eager loading associations in as few queries as possible.
From there you simply add on any conditions you need and whatever gets loaded for ProductGroup will ensure that all of the associated models also get loaded.
Now you just iterate normally over your associations. Assuming @product_groups is has a collection of ProductGroup
The default way that rails sets up associations should fulfill the data structure you asked for, just with actual records instead of a hash of hashes, which you would need to load anyway to create the hash of hashes.