Rails ActiveRecord, selecting distinct fields from a joined table and
returning all the models
I am working on a Rails app with MySQL.
I have a tables like this:
gifts
id, basket_id, orange_id, berry_id
berries
id, action_id, name
These are their models:
class Gift < ActiveRecord::Base
belongs_to :basket
belongs_to :orange
belongs_to :berry
...
end
class Berry < ActiveRecord::Base
belongs_to :action
has_one :gift
...
end
class Basket < ActiveRecord::Base
has_many :gifts
...
end
In the Basket model, I have gifts variable that contains all the gifts for
this basket, through the association I defined in the Basket model -
basically "SELECT * FROM gifts WHERE basket_id = ?", self.id
I want to group all the unique berry actions for each orange.
Current approach:
def get_data
data = {}
gifts.each |gift| do
orange_id = gift.orange_id
data[orange_id] ||= { :basket_id => gift.basket_id, :name =>
gift.orange.name, :actions => Set.new }
data[orange_id] << { :action_name => gift.berry.action.name }
end
return data
My approach was to iterate through gifts and save unique berry actions
into a Set for each unique orange_id, however this approach is slow if I
have thousands of gifts with multiple berry actions for each berry. If
there are 2000 gifts and 4 actions, then I am looping 8000 times.
Gifts can have the same oranges and baskets, but always different berries.
I want to perform this query instead, which will be faster as I will be
iterating through unique oranges instead of all the gifts (for each basket
there a couple hundred oranges only).
SELECT DISTINCT g.basket_id, g.orange_id, g.berry_id, b.action_id
FROM gifts AS g
JOIN berries AS b
ON g.berry_id = b.id
Can someone show me how to do this using Rails ActiveRecord methods? I
would like to be able to iterate through each row of this query and
perform actions on the fields I selected. It would also be great if the
associated models can be returned as well, such that I can grab the
basket, orange, berry, and action model for each row.
No comments:
Post a Comment