23 Oct 2012
Using factory girl and making mass assignment params
versions: factory_girl_rails: 4.1.0, rails: 3.2.8, rspec: 2.11.0
Writing controllers examples are pretty tough. For example, when you have to write some update method examples,
- first we gotta save a data to the DB which we are going to update,
- and prepare params(which is based on the data which we saved in 1.) to send to the update method,
- and finnaly, execute the update method.
and when it goes with the nested object forms, it gets tougher.
I’ll show you how I did it, its kinda messed up, so if you have some better solution, please comment.
FactoryGirl Data(preparation)
first we need to get FactoryGirl ready, so we can get some test data and use those.
lets say we have an Article table and a ArticleBody table, the relations will be like bellow.
It’ll be basic nested objects using nested_attributes_for
and has_many
.
If you don’t understand those, there’s some good tutorial on rails cast which I mentioned here, so look at that.
class Article < ActiveRecord::Base
attr_accessible :title
has_many :article_bodies, :dependent => :delete_all
accepts_nested_attributes_for :article_bodies, :allow_destroy => true
end
class ArticleBody < ActiveRecord::Base
attr_accessible :subtitle, :body
belongs_to :article
end
the factory girl data will be like bellow
FactoryGirl.define do
factory :article, :class => 'Article' do
title "test article title"
factory :article_with_bodies, :class => 'Article' do
ignore do
body_count 3
end
after(:create) do |article, evaluator|
FactoryGirl.create_list(:article_body, evaluator.body_count, article: article)
end
end
end
factory :article_body, :class => 'ArticleBody' do
article
sequence(:subtitle) { |n| "subtitle #{n}"}
sequence(:body) { |n| "body #{n}"}
end
end
I basically read the GETTING_STARTED.md which was in the factory girl repo to get the factory.rb done.
getting shits done :p
now lets look back what we have to do which I mentioned earlier.
- first we gotta save a data to the DB which we are going to update,
- and prepare params(which is based on the data which we saved in 1.) to send to the update method,
- and finnaly, execute the update method.
1. first we gotta save a data to the DB which we are going to update,
this is basic, just like bellow.
@article = FactoryGirl.create(:article_with_bodies)
2. and prepare params(which is based on the data which we saved in 1.) to send to the update method,
this is going to be the tricky part, I did it like this.
params = @article.attributes.except('created_at', 'updated_at')
params['article_bodies_attributes'] = []
@article.article_bodies.count.times do |i|
params['article_bodies_attributes'] << @article.article_bodies[i].attributes.except('created_at', 'updated_at')
end
If you want to change the values inside the article_bodies, you can do it by writing like this.
`params['article_bodies_attributes'][0]['subtitle'] = 'bar'`
3. and finnaly, execute the update method.
put :update, {:id => @article.id, :article => params }
thats it!
feel free to comment :)
Takehiro Adachi at 13:19