Reputation: 800
This is my scenario:
class User < ActiveRecord::Base
has_many :things
# attr_accessible :average_rating
end
class Thing < ActiveRecord::Base
belongs_to :user
has_one :thing_rating
end
class ThingRating < ActiveRecord::Base
belongs_to :thing
attr_accessible :rating
end
I want to have an attribute in my User model which has the average calculation of his related ThingsRating.
What would be the best practice to manage this?
Thanks
Upvotes: 3
Views: 259
Reputation: 6942
May be you can use relation not sure but you can try this
class User < ActiveRecord::Base
has_many :things
has_many :thing_ratings, through: :things
# attr_accessible :average_rating
def avg_rating
@avg_rating ||= thing_ratings.average("thing_ratings.rating")
end
end
Upvotes: 2
Reputation: 32627
The easy way :
class User < ActiveRecord::Base
has_many :things
def avg_rating
@avg_rating ||= average(things.map(&:thing_rating))
end
private
def average(values)
values.inject(0.0) { |sum, el| sum + el } / arr.size
end
end
This is fine as a starter. But if you have a bit of trafic, you might find yourself with scaling problems.
You'll then have to refactor this to avoid making an SQL query to the things every time you call the method for a different user.
You could then have several possibilites :
avg_rating
, which would be updated by the ThingRating
when it's created or updated.ThingRating
is updated or created.These solutions aren't exhaustive of course. And you could find other ones which would better fit your needs.
Upvotes: 2