0

I'm new to RSpec, and trying to get my head around using Factory Girl with associations in controller specs. The difficulty is:

So if I have models like this:

class Brand < ActiveRecord::Base
  belongs_to :org    
  validates :org, :presence => true
end

class Org < ActiveRecord::Base
  has_many :brands
end

And a factory like this:

FactoryGirl.define do
  factory :brand do
    association :org
  end
end

This controller spec fails:

describe BrandsController do
  describe "POST create with valid params" do
    it "creates a new brand" do
      expect {
        post :create, brand: attributes_for(:brand)
      }.to change(Brand, :count).by(1)
    end
  end
end

(And if I comment out "validates :org, :presence => true" it passes)

There are a number of solutions suggested and I think I have been making simple errors which have meant that I have not been able to get any of them to work.

1) Changing the factory to org_id per a suggestion on this page failed a number of tests with "Validation failed: Org can't be blank"

FactoryGirl.define do
  factory :brand do
    org_id 1002
  end
end

2) Using "symbolize_keys" looks promising. Here and here it is suggested to use code like this:

(FactoryGirl.build :position).attributes.symbolize_keys 

I'm not sure how to apply this in my case. Below is a guess that doesn't work (giving the error No route matches {:controller=>"brands", :action=>"{:id=>nil, :name=>\"MyString\", :org_id=>1052, :include_in_menu=>false, :created_at=>nil, :updated_at=>nil}"}):

describe BrandsController do
  describe "POST create with valid params" do
    it "creates a new brand" do
      expect {
        post build(:brand).attributes.symbolize_keys 
      }.to change(Brand, :count).by(1)
    end
  end
end

Update

I almost got this working with Shioyama's answer below but got the error message:

Failure/Error: post :create, brand: build(:brand).attributes.symbolize_keys
ActiveModel::MassAssignmentSecurity::Error:
  Can't mass-assign protected attributes: id, created_at, updated_at

So following this question I changed it to:

post :create, brand: build(:brand).attributes.symbolize_keys.reject { |key, value| !Brand.attr_accessible[:default].collect { |attribute| attribute.to_sym }.include?(key) }

Which worked!

Community
  • 1
  • 1
Derek Hill
  • 5,965
  • 5
  • 55
  • 74

1 Answers1

2

In your solution 2), you have not passed an action to post which is why it is throwing an error.

Try replacing the code in that expect block to:

post :create, brand: build(:brand).attributes.symbolize_keys
Chris Salzberg
  • 27,099
  • 4
  • 75
  • 82