I’m facing a weird behavior in Rails 3 model instantiation.
So, I have a simple model :
class MyModel < ActiveRecord::Base
validates_format_of :val, :with => /^\d+$/, :message => 'Must be an integer value.'
end
Then a simple controller :
def create
@mod = MyModel.new(params[:my_model])
if @mod.save
...
end
end
first, params[:my_model].inspect returns :
{:val => 'coucou :)'}
But after calling @mod = MyModel.new(params[:my_model]) …
Now, if I call @mod.val.inspect I will get :
0
Why am I not getting the original string ?
At the end the validates succeed because val is indeed an integer.
Is this because val is defined as an integer in the database ?
How do I avoid this behavior and let the validation do his job ?
If
valis defined as an integer in your schema then calling@my_model.valwill always return an integer because AR does typecasting. That’s not new to rails 3, it’s always worked that way. If you want the original string value assigned in the controller, try@my_model.val_before_type_cast. Note thatvalidates_format_ofperforms its validation on this pre-typecast value, so you don’t need to specify that there.EDIT
Sorry I was wrong about the “performs its validation on this pre-typecast value” part. Looking at the code of the validation, it calls
.to_son the post-typecast value which in your case returns"0"and therefore passes validation.I’d suggest not bothering with this validation to be honest. If
0is not a valid value for this column then validate that directly, otherwise just rely on the typecasting. If the user enters123 fooyou’ll end up with123in the database which is usually just fine.