因此,每当有人评价商店时,我都希望Shop模型计算其新的平均评级并将其存储在数据库中(而不是每次有人看到它时计算平均值)。所以我编写了后面的代码段,它不起作用。
循环总是迭代一次,无论数据库中存在多少shop_ratings,其商店ID为shop_id。我玩了一下,发现每次提交新的评级时,该函数都会成功调用,但它只运行一次循环并将平均值设置为第一个评级。
我不知道设置评级变量的“查询”是错误的还是循环错误。
class Shop < ActiveRecord::Base
has_many :shop_ratings
attr_accessible :name, :latitude, :longitude
validates_presence_of :name
validates_presence_of :latitude
validates_presence_of :longitude
def distance_to(lat, long)
return (self.longitude - long) + (self.latitude - lat)
end
def find_average
total = 0
count = 0
ratings = ShopRating.all(:conditions => {:shop_id => id})
ratings.each do |submission|
total = total + submission.rating
count = count + 1
end
update_attribute :average_rating, total/count
end
end
答案 0 :(得分:2)
这是一个更好的find_average方法(顺便说一句,它应该被称为set_average_rating,因为你没有找到它,你正在保存它)
def set_average_rating
update_attribute(:average_rating, shop_ratings.average(:rating))
end
如您所见,我们正在利用AR的平均计算方法,该方法返回一个浮点数。 Doc:http://ar.rubyonrails.org/classes/ActiveRecord/Calculations/ClassMethods.html#M000293
说到浮点数,你的现有代码似乎没有正确计算平均值的原因很可能是b / c你没告诉ruby最终的平均值是浮点数,而不是整数。希望您已将您的shop#average_rating字段定义为浮点数或小数而不是整数。
答案 1 :(得分:0)
如果您想知道会发生什么,请将一些调试信息放入您的代码中:
ratings = ShopRating.all(:conditions => {:shop_id => id})
# add this log
Rails.logger.info "==== the raings of this Shop: #{ratings.inspect}"
ratings.each do |submission|
可能你会看到评级只包含1个元素。
所以,我建议你重新实现你的代码:
变化:
# previous:
ratings = ShopRating.all(:conditions => {:shop_id => id})
ratings.each do |submission|
是:
# because you already defined :
# has_many :shop_ratings
shop_ratings.each do |submission|