Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

how to use traits for associated factories?

I need to write a test for associated models.

spec/factories/users.rb:

FactoryGirl.define do
  factory :user do
    sequence(:name){ |i| "us#{i}" }
    sequence(:email){ |i| "us#{i}@ad.ad" }
    password 'qwerty'
    password_confirmation{ |u| u.password } 
    info Faker::Lorem.paragraph(7)

    trait :user_status do
      status_id 0
    end

    trait :manager_status do
      status_id 1
    end

    trait :admin_status do
      status_id 2
    end    
  end 
end

but file spec/factories/users.rb is empty.

schema:

create_table "statuses", force: :cascade do |t|
  t.string "title"
end

create_table "users", force: :cascade do |t|
  t.string   "email",                  default: "", null: false
  t.string   "encrypted_password",     default: "", null: false
  t.integer  "status_id",              default: 0
  t.string   "name"  
end

the page index.html.erb contains the below code:

....
...
<div class="status"><%= user.status.title if user.status_id %></div>
....
..

when i run a test:

it 'check response status code for index page' do
  visit users_path
  expect(response).to be_success 
end 

console displays follow error messages:

 Failure/Error: visit users_path
 ActionView::Template::Error:
   undefined method `title' for nil:NilClass

How to write factories for 'user' and 'status' with a trait?

like image 672
stackow1 Avatar asked Sep 26 '22 19:09

stackow1


1 Answers

eirikir's solution is pretty close but the Status still wouldn't have a title.

Try this:

spec/factories/users.rb

FactoryGirl.define do
  factory :user do
    sequence(:name){ |i| "us#{i}" }
    sequence(:email){ |i| "us#{i}@ad.ad" }
    password 'qwerty'
    password_confirmation{ |u| u.password } 
    info Faker::Lorem.paragraph(7)

    trait :regular do
      association :status, factory: :user_status
    end

    trait :manager do
      association :status, factory: :manager_status
    end

    trait :admin do
      association :status, factory: :admin_status
    end    
  end 
end

spec/factories/statuses.rb

FactoryGirl.define do
  factory :user_status, class: Status do
    title 'User'
  end

  factory :manager_status, class: Status do
    title 'Manager'
  end

  factory :admin_status, class: Status do
    title 'Admin'
  end
end

In your specs, create your User:

create(:user, :regular)
create(:user, :manager)
create(:user, :admin)

or

build(:user, :regular)
build(:user, :manager)
build(:user, :admin)

etc..

Hope that helps!

like image 120
madcow Avatar answered Sep 30 '22 06:09

madcow