ActiveRecord属性取决于其他模型的计算

时间:2013-04-18 11:47:07

标签: ruby-on-rails ruby-on-rails-3 activerecord

这是我的情景:

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

我想在我的用户模型中有一个属性,它具有相关的ThingsRating的平均值。

管理此问题的最佳做法是什么?

由于

2 个答案:

答案 0 :(得分:2)

可能你可以使用关系不确定,但你可以试试这个

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

答案 1 :(得分:1)

简单方法:

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

作为首发,这很好。但如果你有一点交通,你可能会发现自己有缩放问题。

然后,您必须重构此操作,以避免每次为其他用户调用该方法时对事物进行SQL查询。
然后你可以有几个可能性:

  • 在您的用户数据库avg_rating中添加一个字段,该字段将在ThingRating创建或更新时更新。
  • 每次更新或创建ThingRating时,使用memcached或redis数据库缓存该值并使缓存无效。

当然,这些解决方案并非详尽无遗。你可以找到更符合你需求的其他产品。