Ruby on rails 为什么当我的其他属性有值时,我的[:Rating]属性为nil?
我正试图建立一个评级系统。我最近升级了我的迁移文件Ruby on rails 为什么当我的其他属性有值时,我的[:Rating]属性为nil?,ruby-on-rails,ruby,activerecord,attributes,null,Ruby On Rails,Ruby,Activerecord,Attributes,Null,我正试图建立一个评级系统。我最近升级了我的迁移文件 class AddRatingsToPictures < ActiveRecord::Migration def change add_column :pictures, :ratings_count, :integer add_column :pictures, :rating_total, :integer add_column :pictures, :rating, :integer end end
class AddRatingsToPictures < ActiveRecord::Migration
def change
add_column :pictures, :ratings_count, :integer
add_column :pictures, :rating_total, :integer
add_column :pictures, :rating, :integer
end
end
下面是我在Rails控制台中尝试的一些东西
p = Picture.find(1)
p.rating == nil
false
p[:rating] == nil
true
我认为问题在于这个片段
def rating
self[:rating] || 0
return 0 if self.ratings_count == 0
(self.rating_total.to_f / self.ratings_count).round(2)
end
如果我对一个对象调用.rating,它将返回正确的等级。如果我对一个对象调用[:rating],它将返回nil
我问这个问题的原因是因为我需要这个用于活动记录查询,在这里我必须调用实际属性。具体来说,这行代码
<% Picture.where("rating >= 4.5").order(rating: :desc, title: :asc).each do |picture| %>
因此,我的方法似乎可以为我的模型创建属性。原因可能是我的add_评级方法
def add_rating(rating)
return if rating.nil? || rating == 0
self.ratings_count += 1
self.rating_total += rating.to_i
self.stars = (self.rating_total.to_f / self.ratings_count)
self.save
end
上面,我调用了save方法,它可能在模型中记录了属性
我想我已经很接近了,但看起来我需要帮助。任何建议都将不胜感激。提前感谢。这可能无法解决添加评级的问题,但您可以在迁移中设置默认值,使它们永远不会为零,并且您可以简化每个方法的逻辑,这样可能更容易跟踪问题
class AddRatingsToPictures < ActiveRecord::Migration
def change
add_column :pictures, :ratings_count, :integer, default: 0
add_column :pictures, :rating_total, :integer, default: 0
add_column :pictures, :rating, :integer, default: 0
end
end
class AddRatingsToPictures
picture[:rating]
返回列在数据库中的实际属性值,因此,如果数据库中的值未设置,它将返回nil
,即使您在迁移中将类型设置为整数
在您的代码中,有许多条件,如self[:rating]| | 0
和if rating.nil?|评级==0
。这变得越来越复杂,因为您期望nil
或0
。克服这种复杂性的最简单方法是告诉数据库不允许空值,并设置一些默认值(在您的示例中为0)。您应该进行如下迁移:
class AddRatingsToPictures < ActiveRecord::Migration
def change
add_column :pictures, :ratings_count, :integer, null: false, default: 0
add_column :pictures, :rating_total, :integer, null: false, default: 0
add_column :pictures, :rating, :integer, null: false, default: 0
end
end
现在,看看代码,您正在将一些属性星号
设置为平均评级。实际的评级
属性根本没有设置。没有足够的信息让我确定,但我假设明星
应该是评级
?那么你会得到:
def add_rating(rating)
return if rating.to_i == 0
self.ratings_count += 1
self.rating_total += rating.to_i
self.rating = (rating_total.to_f / ratings_count)
self.save
end
好吧,我解决了问题。这是因为我将评级存储为整数,而不是小数
add_column :pictures, :rating, :integer, default: 0, null: false
应该是
add_column :pictures, :rating, :decimal, default: 0, null: false
我的方法要求我将ratings_total除以ratings_count的整数。我使用类型转换将数字转换为十进制,但值本身存储为整数
更改迁移解决了这个问题。我认为这不是答案。我的ratings\u count和ratings\u total属性不是零,我没有包括默认值:0。这可能值得一看。这是有潜力的,不幸的是,这条线是一个问题。自我评级\总+=评级。这将导致TypeError:无法将字符串强制转换为fixnum。我知道我们将类型设置为整数,但可能需要先将rating_total转换为浮点。我会调查的。我们还删除了ratings_total和ratings_count方法。我猜参数应该是字符串。我更新了答案,将其转换为整数。你已经准备好了这个角色,我想我有点太想移除它了;)很好,这解决了我的问题。但是[:rating]仍然设置为0,而不是计算的等级。
def add_rating(rating)
return if rating.to_i == 0
self.ratings_count += 1
self.rating_total += rating.to_i
self.rating = (rating_total.to_f / ratings_count)
self.save
end
add_column :pictures, :rating, :integer, default: 0, null: false
add_column :pictures, :rating, :decimal, default: 0, null: false