2010-07-27 53 views
3

认为我有一个迁移如下不能理解导轨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 

这是怎么发生的?因为我分配一个错误的值不应该会引发错误?

最大的问题是以下几点。

因为它会自动转换我验证方法失败惨败。

更新 -the validate方法

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

你使用什么验证方法?如果您使用'validates_numericality_of:the_dummy_number',它应该可以正常工作 – 2010-07-27 09:22:14

+0

检查更新 – ZX12R 2010-07-27 09:27:52

+0

您的验证方法不会进行任何验证! – 2010-07-27 09:51:38

回答

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方法的价值得到它之前类型转换并分配给内部十进制值。

+0

非常感谢你.. – ZX12R 2010-07-27 09:56:09

相关问题