Elmor
Elmor

Reputation: 4905

shoulda factory girl error Couldn't find model without an ID

Good day, i get this error from

 ActiveRecord::RecordNotFound:
   Couldn't find User without an ID

my model

 has_many :objects, class_name: 'OrderObject', dependent: :destroy
  belongs_to :user
  belongs_to :tariff

  validates :client, :phone, :tariff_id, :days, :user_id, presence: true

spec

 before do
    user = FactoryGirl.create(:user)
    FactoryGirl.create(:order, user_id: user.id)
  end
      context "validations" do
       it { should validate_presence_of :client  }
       it { should validate_presence_of :phone }
       it { should validate_presence_of :tariff_id }
       it { should validate_presence_of :days }
      end

      it { should have_many(:objects) } 
      it { should belong_to(:tariff) }
      it { should belong_to(:user) }

factory

factory :order do
    client "MyString"
    phone "MyString"
    tariff_id 1
    days 1
    # advt_payed_day 1
    # firm_payed_day 1
    user_id 1
  end

UPDATE 1

changed to
  before(:all) do
   user = FactoryGirl.create(:user )
   puts  user.id 
   order = FactoryGirl.create(:order, user_id: user.id ) 
   puts order.id

  end

output

Order
45
32
  should have many objects
  should belong to tariff
  should belong to user
  validations
    should require client to be set (FAILED - 1)
    should require phone to be set (FAILED - 2)
    should require tariff_id to be set (FAILED - 3)
    should require days to be set (FAILED - 4)
    should require user_id to be set (FAILED - 5)

so order & user are created...

Update 2 as Rubyman suggested, i've changed couple of things:

in spec
  before(:all) do
   user = FactoryGirl.create(:user )
   #puts  user.id 
   order = FactoryGirl.create(:order, user_id: user.id ) 
   puts order 
   puts order.user_id

  end

in the factory

  factory :order do
    client "MyString"
    phone "MyString"
    tariff_id 1
    days 1
    # user_id 1
    association :user, factory: :user
  end

and output is:

Order
#<Order:0x00000005a866a0>
46
  should have many objects
  should belong to tariff
  should belong to user
  validations
    should require client to be set (FAILED - 1)
    should require phone to be set (FAILED - 2)
    should require tariff_id to be set (FAILED - 3)
    should require days to be set (FAILED - 4)
    should require user_id to be set (FAILED - 5)

1) Order validations 
     Failure/Error: it { should validate_presence_of :client  }
     ActiveRecord::RecordNotFound:
       Couldn't find User without an ID
     # ./app/models/order.rb:35:in `user_is_not_admin?'
     # ./spec/models/order_spec.rb:14:in `block (3 levels) in <top (required)>'

update 3 after reading advice from tdgs here are the changes: in model no changes :

validates :client, :phone, :tariff_id, :days, :user_id, presence: true

in spec

describe Order do
  before(:each) do
   user = FactoryGirl.create(:user )
   #puts  user.id 
   order = FactoryGirl.create(:order, user_id: user.id ) 
   puts order 
   puts order.user_id
   puts order.tariff_id
   puts order.phone
   puts order.days
   puts order.client
   puts '*****'
   user = User.find(order.user_id)
   puts user.login

  end
  context "validations" do
   it { should validate_presence_of :client  }
   it { should validate_presence_of :phone }
   it { should validate_presence_of :tariff_id }
   it { should validate_presence_of :days }
   it { should validate_presence_of :user_id }
  end

  it { should have_many(:objects) } 
  it { should belong_to(:tariff) }
  it { should belong_to(:user) }
end

output:

#<Order:0x00000006c10ce0>
161
101
MyString
1
MyString
*****
user__7
    should require days to be set (FAILED - 1)

output for every should is valid as far as i see...

UPDATE N should have written it in the beginning. i've run (hoped that it'll solve this issue) in console

bundle exec rake db:migrate
bundle exec rake db:migrate:reset db:test:prepare

Upvotes: 1

Views: 1628

Answers (4)

tdgs
tdgs

Reputation: 1096

First, your factory definition is not defining associations correctly. You should have something like this:

FactoryGirl.define do
  factory :user do
    sequence(:username) {|n| "username_#{n}"}
    # more attributes here
  end

  factory :tariff do
   # attributes
  end

  factory :order do
    client "MyString"
    phone "MyString"
    tariff
    user
    days 1
  end
end

Then your tests should be written like this:

 context "validations" do
   it { should validate_presence_of :client  }
   it { should validate_presence_of :phone }
   it { should validate_presence_of :tariff_id }
   it { should validate_presence_of :days }
  end

  it { should have_many(:objects) } 
  it { should belong_to(:tariff) }
  it { should belong_to(:user) }

All the code you currently have in the before filter is not relevant right now. Also notice that using before(:all) might have some strange effects when running your tests, because they do not run inside a transaction. before(:each) on the other hand does.

Upvotes: 1

Elmor
Elmor

Reputation: 4905

i moved away from shoulda and rewrote checks for validation. This way it works:

 before(:each) do
   @user = FactoryGirl.create(:user )
   @order = FactoryGirl.create(:order, user_id: @user.id ) 

  end
   it 'absence of client isn\'t acceptable' do
      temp = @order.client
      @order.client = ''
      @order.should_not be_valid
      @order.client = temp
      @order.should be_valid
    end

Upvotes: 0

Rubyman
Rubyman

Reputation: 874

Check how to create associations with factory girl https://github.com/thoughtbot/factory_girl/blob/master/GETTING_STARTED.md

Upvotes: 0

Dipak Panchal
Dipak Panchal

Reputation: 6036

try this

  before { 
   @user = FactoryGirl.create(:user, :email => "test.com", :password => "test123", ... )
   @order = FactoryGirl.create(:order, :user_id => @user.id ) 
  }

Factory

require 'factory_girl'
FactoryGirl.define do
 factory :order do
  client "MyString"
  ...
  ...
 end
end

Upvotes: 0

Related Questions