cannot understand rails activerecord typecast reasons
consider that i have a migration as follows
create_table :dummies do |t|
t.decimal :the_dummy_number
end
i instantiate like the following
dummy = Dummy.new
dummy.the_dummy_number = "a string"
puts dummy.the_dummy_number
the output for the above is
0.0
how did this happen? since i assign a wrong value开发者_如何学运维 shouldn't it raise an error?
The biggest problem is the following.
Since it automatically converts my validate method fails miserably.
update-the validate method
validate :is_dummy_number_valid, :the_dummy_number
def is_dummy_number_valid
read_attribute(:the_dummy_number).strip()
end
The reason that this does not work as you expect is that the underlying ruby implementation of BigDecimal does not error when passed a string.
Consider the following code
[ '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
So BigDecimal scans the string and assigns anything at the beginning of the string that could be a decimal to its value.
If you set your model up like this
class Dummy < ActiveRecord::Base
validates_numericality_of :the_dummy_number
end
Then the validation should work fine
>> 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"}
This works because the validates_numericality_of macro uses the raw_value method to get at the value before it was typecast and assigned to the internal decimal value.
精彩评论