Rails使用整数进行定价

时间:2013-09-15 13:30:03

标签: ruby-on-rails

我有一个带有价格字段的预订模型。我选择了一个Integer数据类型来存储便士的价格,并在我的预订模型中有一个before_create调用,将用户输入的价格换算成磅数到便士:

before_create { self.price = price * 100 } #convert to pence

但是,我注意到在我的终端中,如果我在表单上输入一个十进制数字(例如22.75),它将被输入我的模型2200而不是2275.

我认为这是因为价格字段是一个整数,因此它会将22.75转换为22然后再将​​转换应用于便士。

我是否应该在我的控制器中解决这个问题?您认为或模型是正确的方法吗?

编辑我决定使用DECIMAL而不是INTEGER来避免潜在的头痛。关于这个主题有很多争论,但大多数人似乎都建议使用DECIMAL。感谢大家的建议。

3 个答案:

答案 0 :(得分:1)

我会去转换模型之外的值。如果您从模型转换,很快或以后,将会发生棘手的事情。例如,您可以提供便士值,它仍然会增加100倍。

始终以正确的单位设置值可以避免任何错误:如果价格是便士,请始终将其设置为便士。从磅到便士的转换更像是帮助者或自由人应该做的事情。

答案 1 :(得分:0)

尝试添加一些辅助方法。

class Booking < ActiveRecord::Base
  def price_dollars
    self.price / 100
  end

  def price_dollars=(val)
    self.price = val * 100
  end
end

这应该有帮助,以便当它设置时它将* 100并且当显示时只使用booking1.price_dollars进行十进制显示。

答案 2 :(得分:0)

最好不要谈论过滤器。问题不在那里。

我对你的问题做了一个实验。

在我的一个演示应用程序中,我有一个模型任务。然后我在整数类型中添加了一个price字段,并复制了你的before_create过滤器。

结果呢?它在不触及过滤器的情况下得到相同的结果。

task = Task.new(title: 'foo', price: 22.75)
task.title
#=> 'foo'
task.price
#=> 22
task.price.to_f
#=> 22.0

请参阅,在对象初始化时,该值已转换为整数。过滤器甚至已经生效。

因此,对于您的情况,我认为最好的解决方案是使其保持一致,将所有价格保存为便士,并在需要时进行转换。

模型中的另一个考虑因素

当然,对于当前的修复,控制器中的处理数据是可行的。

另一种可能的方法是编写另一种基于#new

的方法
class Booking < ActiveRecord::Base
  # ....
  # Remove that callback

  def new_with_price_format(*args)
    if args[:price].is_a?(Float)
       args[:price] *= 100
    end
    new(*args)
  end

然后在控制器中

  @booking = Booking.new_with_price_format(params[:booking])