42

Looking through a tutorial on controller testing the author gives an example of an rspec test testing a controller action. My question is, why did they use the method attributes_for over build? There is no clear explanation why attributes_for is used besides that it returns a hash of values.

it "redirects to the home page upon save" do
  post :create, contact: Factory.attributes_for(:contact)
  response.should redirect_to root_url
end

The tutorial link is found here: http://everydayrails.com/2012/04/07/testing-series-rspec-controllers.html The example is found at the beginning topic section Controller testing basics

thank_you
  • 11,001
  • 19
  • 101
  • 185

1 Answers1

73

attributes_for will return a hash, whereas build will return a non persisted object.

Given the following factory:

FactoryGirl.define do
  factory :user do
    name 'John Doe'
  end
end

Here is the result of build:

FactoryGirl.build :user
=> #<User id: nil, name: "John Doe", created_at: nil, updated_at: nil>

and the result of attributes_for

FactoryGirl.attributes_for :user
=> {:name=>"John Doe"}

I find attributes_for very helpful for my functional test, as I can do things like the following to create a user:

post :create, user: FactoryGirl.attributes_for(:user)

When using build, we would have to manually create a hash of attributes from the user instance and pass it to the post method, such as:

u = FactoryGirl.build :user
post :create, user: u.attributes # This is actually different as it includes all the attributes, in that case updated_at & created_at

I usually use build & create when I directly want objects and not an attributes hash

Let me know if you need more details

pjam
  • 6,356
  • 5
  • 30
  • 40
  • Thanks pjam, I understand it now! You are becoming more and more of an rspec mentor for me in overstackflow. – thank_you Oct 31 '12 at 02:23
  • been looking for this answer all over. One thign though... how would I get around `post :create, user: u.attributes` if some of those attributes aren't accessible in the model? – Adam Waite May 28 '13 at 22:59
  • I'm not sure I understand what you want, do you mean if some attributes are not in the attr_accessible list ? Then I don't see what the issue is, I might be missing something here – pjam May 28 '13 at 23:33
  • 1
    @AdamWaite check out .except as shown in http://stackoverflow.com/questions/1560572/ruby-delete-multiple-hash-keys to remove attributes from the hash generated by FactoryGirl. – Anthony Panozzo Nov 22 '13 at 17:40
  • I'm getting an error: SyntaxError: unexpected ':', expecting end-of-input post: :create, user: FactoryGirl.attributes_for(:user) ... where after "post:" the console is expecting something else – carl crott Apr 18 '15 at 05:10