I want to use FactoryGirl.attributes_for in controller testing, as in:
it "raise error creating a new PremiseGroup for this user" do
expect {
post :create, {:premise_group => FactoryGirl.attributes_for(:premise_group)}
}.to raise_error(CanCan::AccessDenied)
end
... but this doesn't work because #attributes_for omits the :user_id attribute. Here is the difference between #create
and #attributes_for
:
>> FactoryGirl.create(:premise_group)
=> #<PremiseGroup id: 3, name: "PremiseGroup_4", user_id: 6, is_visible: false, is_open: false)
>> FactoryGirl.attributes_for(:premise_group)
=> {:name=>"PremiseGroup_5", :is_visible=>false, :is_open=>false}
Note that the :user_id is absent from #attributes_for
. Is this the expected behavior?
FWIW, my factories file includes definitions for :premise_group
and for :user
:
FactoryGirl.define do
...
factory :premise_group do
sequence(:name) {|n| "PremiseGroup_#{n}"}
user
is_visible false
is_open false
end
factory :user do
...
end
end
I think this is a slight improvement over fearless_fool's answer, although it depends on your desired result.
Easiest to explain with an example. Say you have lat and long attributes in your model. On your form, you don't have lat and long fields, but rather lat degree, lat minute, lat second, etc. These later can converted to the decimal lat long form.
Say your factory is like so:
fearless's
build_attributes
would return{ lat: nil, long: nil}
. While thebuild_attributes
below will return{ lat_d: 12, lat_m: 32..., lat: nil...}
To further elaborate on the given
build_attributes
solution, I modified it to only add the accessible associations:Digging deep into the FactoryGirl documentation, e.g. this wiki page, you will find mentions that
attributes_for
ignores associations. Ours is not to wonder why (but I did submit an issue)(but see update below). As a workaround, I've wrapped a helper method aroundFactoryGirl.build(...).attributes
that stripsid
,created_at
, andupdated_at
:So now:
... which is exactly what's expected.
update
Having absorbed the comments from the creators of FactoryGirl, I understand why
attributes_for
ignores associations: referencing an association generates a call to the db which can greatly slow down tests in some cases. But if you need associations, thebuild_attributes
approach shown above should work.Here is another way:
FactoryGirl.build(:car).attributes.except('id', 'created_at', 'updated_at').symbolize_keys
Limitations:
create
, as inassociation :user, strategy: :create
. This strategy can make your factory very slow if you don't use it wisely.