我正在尝试重新计算模型的after_update回调中的百分比。
def update_percentages
if self.likes_changed? or self.dislikes_changed?
total = self.likes + self.dislikes
self.likes_percent = (self.likes / total) * 100
self.dislikes_percent = (self.dislikes / total) * 100
self.save
end
end
这不起作用。百分比总是以100或0出现,这完全破坏了一切。
我在哪里滑倒?我保证self.likes和self.dislikes正在递增。
答案 0 :(得分:5)
当您将整数除以整数(又名整数除法)时,大多数编程语言(包括Ruby)都假设您希望结果为整数。这主要是由于历史记录,因为对于数字的较低级别表示,整数与具有小数点的数字非常不同,并且使用整数除以多更快。因此,您的百分比(0到1之间的数字)的十进制截断,因此变为0或1.当乘以100时,变为0或100。
如果除法中的任何数字不是整数,则不执行整数除法。替代方案是带小数点的数字。有这样的几种类型的数字,但通常它们被称为浮点数,而在Ruby中,最典型的浮点数是Float类。
1.0.class.ancestors
# => [Float, Precision, Numeric, Comparable, Object, Kernel]
1.class.ancestors
# => [Fixnum, Integer, Precision, Numeric, Comparable, Object, Kernel]
在Rails的模型中,浮点数用Ruby Float类表示,而decimal用Ruby BigDecimal类表示。不同之处在于BigDecimals更准确(即可用于赚钱)。
通常情况下,您可以将您的号码“强制转换”为浮点数,这意味着您不再进行整数除法。然后,如果需要,您可以在计算后将其转换回整数。
x = 20 # => 20
y = 30 # => 30
y.to_f # => 30.0
x.class # => Fixnum
y.class # => Fixnum
y.to_f.class # => Float
20 / 30 # => 0
20 / 30.0 # => 0.666666666666667
x / y # => 0
x / y.to_f # => 0.666666666666667
(x / y.to_f).round # => 1
在你的情况下,假设你想要整数结果(即42%为42%),我认为最简单的方法是在除法之前乘以100。这会将你的小数点推到分割前的最右边,这意味着你的数字和以前一样准确。
before_save :update_percentages
def update_percentages
total = likes + dislikes
self.likes_percent = 100 * likes / total
self.dislikes_percent = 100 * dislikes / total
end
注意:
self
你只需要它们来分配创建局部变量的歧义,并且当你有一个局部变量来消除你想要调用方法而不是引用变量答案 1 :(得分:2)
因为喜欢/不喜欢是整数值而整数/整数=整数。
所以你可以做两件事之一,转换为Float或改变你的操作顺序。
self.likes_percent = (self.likes.to_f/total.to_f) * 100
或者,保持一切整数
self.likes_percent = (self.likes * 100)/total
答案 2 :(得分:1)
我不确定这是你遇到的唯一问题,但在保存对象后会调用after_update
。
尝试更改之前的update_percentages
- 代替before_update
或before_validate
。另外,删除self.save
行 - 如果您使用其中一个回调,它将在稍后自动调用。