【发布时间】:2014-09-21 11:43:43
【问题描述】:
我正在创建一个图片评分应用程序,用户可以在其中点击图片并按 1 到 5 的等级对它们进行评分。我正在尝试计算一张图片的平均评分。在用户点击评分值之前,该值成为图片的评分。
Rating: 5
如果用户点击 1,评分将变为 1
Rating: 1
在现实中,评分应该是 3。
(5 + 1) / 2
=> 3
这是我迄今为止在实现此功能方面所取得的成就。
我添加了一个迁移来为我的图片表创建两个新列
rails g migration AddRatingsToPictures ratings_count: integer, rating_total: integer
新的属性 rating_count 和 rating_total 都是整数类型,这意味着它们默认分配为 nil 值。
p = Picture.first
p.attribute_names
=> ['id', 'title', 'category', 'stars', 'updated_at', 'created_at',
'ratings_count', 'rating_total']
p.ratings_count
=> nil
p.rating_total
=> nil
我唯一的问题是 NilClass 错误。
这是我的 PicturesController 中的更新方法。
def update
@picture = Picture.find(params[:id])
@picture.ratings_count = 0 if @picture.stars.nil?
@picture.rating_total = @picture.stars
@picture.rating_total += @picture.stars if @picture.stars_changed?
@picture.ratings_count += 1 if @picture.rating_total_changed?
if @picture.update_attributes(picture_params)
unless current_user.pictures.include?(@picture)
@picture = Picture.find(params[:id])
current_user.pictures << @picture
redirect_to @picture, :flash => { :success => "Thank you! This picture has been added to your Favorites List" }
else
redirect_to :action => 'index'
flash[:success] = 'Thank you! This picture has been updated'
end
else
render 'edit'
end
end
这是我的 PicturesController 中的图片参数方法
def picture_params
params.require(:picture).permit(:title, :category, :genre, :stars)
end
这是两个新列的作用
ratings_count: Calculates the number of times a picture has been rated
rating_total: Calculates the sum of the stars a picture has received
在上面的代码中,如果图片没有评分,我首先将 rating_count 设置为 0。这意味着该图片尚未评级。
然后我需要最初将 rating_total 设置为图片的星数。如果用户更改了星级,我会将这些星级添加到 rating_total。如果总数增加,这就是我增加收视率的提示。
显然,要计算平均值,我会这样做。
(@picture.rating_total / @picture.ratings_count).to_f
现在,我认为我的想法是正确的,但我知道为什么这不起作用。当使用整数值创建列时,默认情况下它们设置为 nil。当我加载网页时,这会导致 NilClass 错误。
undefined method `/' for nil:NilClass
这是我在视图中的代码
<li><strong>Rating:</strong> <%= pluralize((@picture.rating_total / @picture.ratings_count), 'Star') %></li>
【问题讨论】:
-
如果你想计算一个平均值,你要么必须: 1) 保存一个评级数组,然后计算 - 即
(@picture.star_ratings.inject(0) { |total, v| total = total + v } / @picture.star_ratings.count)(或者你可以使用 SQL也计算一下)2)在数据库中分别保存“总评分数”和“总评分数”。@picture.rating_total / @picture.rating_count -
@JustinAiken 这应该是一个答案
标签: ruby-on-rails ruby methods updates rating