无法理解rails activerecord类型的原因

时间:2010-07-27 09:09:31

标签: ruby-on-rails ruby activerecord

考虑我的迁移如下

create_table :dummies do |t|
  t.decimal :the_dummy_number
end 

我实例化如下

dummy = Dummy.new
dummy.the_dummy_number = "a string"
puts dummy.the_dummy_number

上面的输出是

 0.0
  

这是怎么发生的?因为我指定了错误的值不应该引发错误吗?

最大的问题如下。

由于它自动转换我的验证方法失败了。

更新 - 验证方法

 validate :is_dummy_number_valid, :the_dummy_number
 def is_dummy_number_valid
    read_attribute(:the_dummy_number).strip()
 end

1 个答案:

答案 0 :(得分:3)

这不能按预期工作的原因是BigDecimal的基础ruby实现在传递字符串时不会出错。

考虑以下代码

[ 'This is a string', '2is a string', '2.3 is also a string', 
  '   -3.3 is also a string'].each { |d| puts "#{d} = #{BigDecimal.new(d)}" }

This is a string = 0.0
2is a string = 2.0
2.3 is also a string = 2.3
   -3.3 is also a string = -3.3

因此BigDecimal会扫描字符串并在字符串的开头指定任何可能是其值的小数的内容。

如果你像这样设置你的模型

class Dummy < ActiveRecord::Base

   validates_numericality_of :the_dummy_number

end

然后验证应该正常

>> d=Dummy.new(:the_dummy_number => 'This is a string')
=> #<Dummy id: nil, the_dummy_number: #<BigDecimal:5b9230,'0.0',4(4)>, created_at: nil, updated_at: nil>

>> puts d.the_dummy_number
0.0
=> nil
>> d.valid?
=> false

>> d.errors
=> #<ActiveRecord::Errors:0x5af6b8 @errors=#<OrderedHash
  {"the_dummy_number"=>[#<ActiveRecord::Error:0x5ae114 
   @message=:not_a_number, @options={:value=>"This is a string"}

这是有效的,因为validates_numericality_of宏使用raw_value方法获取类型转换之前的值并将其分配给内部十进制值。