I have these factories setup:
FactoryGirl.define do
factory :product do
name { Faker::Commerce.product_name }
price { Faker::Commerce.price }
image { Faker::Internet.url }
end
factory :new_product, parent: :product do
name nil
price nil
image nil
end
factory :string_product, parent: :product do
price { Faker::Commerce.price.to_s }
end
end
Why do I want to use :string_product? Well, although the price attribute is of datatype float at the database level, occasionally I want to build a Factory with all of the attributes as strings.
This is so I can build the factory and then run expectations against its attributes when they are passed into the params hash. (All params from the URL are strings)
However, in the rails console:
> FactoryGirl.build :string_product
=> #<Product:0x00000007279780 id: nil, name: "Sleek Plastic Hat", price: 43.54, image: "http://blick.name/moie", created_at: nil, updated_at: nil>
As you can see, price
is still being saved as a string.
An experiment to attempt to see what's going on:
...
factory :string_product, parent: :product do
price { "WHY ARE YOU NOT A STRING?" }
end
...
results in:
=> #<Product:0x000000077ddfa0 id: nil, name: "Awesome Steel Pants", price: 0.0, image: "http://rogahn.com/kavon", created_at: nil, updated_at: nil>
My string is now converted to the float 0.0
How do I prevent this behavior? If I want to have one of my attributes as a string, especially when I'm only build
ing it I should be allowed to. Is there a FactoryGirl configuration where I can stop this happening? Exactly the same thing happens with the Fabrication
gem, so I'm guessing this is something to do with the model? My Product
model is literally empty right now...no validations or anything, so how can that be? The only way FactoryGirl knows price is a float is because it has that datatype on the database level.
Anyway, this is really annoying, if someone could show me how to let me write strings to my Factory's attributes I would be very appreciative. I could use .to_s
in the spec itself but I want to keep my specs clean as possible and thought factories would be a great place to keep this configuration...
Is there a fabrication library that would let me do this?
Just some more experimentation:
> "WHY ARE YOU NOT A STRING".to_f
=> 0.0
Okay, so somewhere, in rails or in factorygirl, to_f
is being called on my beloved string. Where? And how do I stop it?
With
fabrication
you need to useattributes_for
to generate a hash representation of your object. It will bypass theActiveRecord
model entirely so nothing should be coerced.Fabricate.attributes_for(:string_product)