Nested factory girl with nested attributes in Rails - ruby-on-rails

There are 2 factories (using FactoryGirl):
FactoryGirl.define do
factory :owner do
name 'Some name'
email 'test#gmail.com'
phone '89020000000'
password '123456'
password_confirmation '123456'
role
end
end
And roles:
FactoryGirl.define do
factory :role do
description 'Owner'
end
factory :superuser_role do
description 'Superuser'
end
end
I want to add a :superuser factory that has the same fields as :owner except role. How can I do it? Thanks.

I think this will work
FactoryGirl.define do
factory :owner do
name 'Some name'
email 'test#gmail.com'
phone '89020000000'
password '123456'
password_confirmation '123456'
role
factory :superuser do
association :role, factory: :superuser_role
end
end
end

Related

Factory bot error "private method `new' called for User:Class (NoMethodError)"

I m new to factory bot, I try to create a sample data using factory bot but I got this error
How to resolve this error?
features/support/factories.rb:
require 'factory_bot'
FactoryBot.define do
factory :user do
email "xxx123#xyz.co"
password "asdf123"
password_confirmation "asdf123"
end
end
FactoryBot.define do
factory :post do
user = FactoryBot.create(:user)
end
end
require 'factory_bot'
FactoryBot.define do
factory :user do
email "xxx123#xyz.co"
password "asdf123"
password_confirmation "asdf123"
end
end
FactoryBot.define do
factory :post do
user
end
end
as described in FactoryBot documentation
Associations
It's possible to set up associations within factories. If the factory name is the same as the association name, the factory name can be left out.
factory :post do
# ...
author
end
You can also specify a different factory or override attributes:
factory :post do
# ...
association :author, factory: :user, last_name: "Writely"
end

Factory girl association self referencing the parent model

In my application an account can have a single owner (user) and multiple users.
In my tests I do this:
# account_factory_static.rb
FactoryGirl.define do
factory :account do
name 'demoaccount'
association :owner, :factory => :user
end
end
# user_factory_static.rb
FactoryGirl.define do
factory :user do
email 'demo#example.com'
first_name 'Jon'
last_name 'Doe'
password 'password'
end
end
and use them like below:
let(:account) { FactoryGirl.create(:account) }
The problem is that right nowaccount.users.count equals 0 because I have no way to do something like #account.users << #account.owner like I do in my controllers when a user signs up.
The question is how can I add the associated account's id to the account_id attribute of the user in FactoryGirl?
In other words how do you do it in FactoryGirl?
Thanks.
You can use after :create block for it:
FactoryGirl.define do
factory :account do
name 'demoaccount'
association :owner, :factory => :user
after :create do |account|
account.users << account.owner
end
end
end

Has_many Association in FactoryGirl

I have 2 classes Users and Authentications, then Authentications has_many Users:
User class:
FactoryGirl.define do
factory :user do
first_name "Juan"
last_name "Iturralde"
sequence(:email) { |n| "person-#{n}#example.org" }
password "1234567890"
password_confirmation "1234567890"
is_admin false
factory :admin do
is_admin true
end
after(:create) do |user|
create(:authentication, user: user)
end
end
end
Authentication class:
FactoryGirl.define do
factory :authentication do
user {User.first || create(:user)}
provider "Apple"
uid "uid"
end
end
And i dont now. How create an user in authentication?
To build associations in specs I use the following:
# spec/factories/posts.rb
FactoryGirl.define do
factory :post do
title 'The best post'
trait :with_comments do
create_list :comment, 3
end
end
end
# spec/factories/comments.rb
FactoryGirl.define do
factory :comment do
post
content 'Really awesome post'
end
end
# in specs
. . .
let(:post_with_commments) { create :post, :with_comments }
. . .

how to create a factory for a relationship between two users

I want create a factory for a Relationship model which contains two attributes followed_id and follower_id but i have no idea how to do this, this is my factories file :
FactoryGirl.define do
factory :user do
sequence(:name) { |n| "Person #{n}" }
sequence(:email) { |n| "person_#{n}#example.com"}
password "foobar"
password_confirmation "foobar"
end
factory :relationship do
# i need something like this
# followed_id a_user.id
# follower_id another_user.id
end
end
update
what i want to do with this relationship factory is to test that if i destroy a user, all his relationships will be destroyed too, this is my test :
describe "relationships associations" do
let!(:relationship) { FactoryGirl.create(:relationship) }
it "should destroy associated relationships" do
relationships = #user.relationships.to_a
#user.destroy
expect(relationships).not_to be_empty
relationships.each do |relationship|
expect(Relationships.where(id: relationship.id)).to be_empty
end
end
end
In my experience such "relationship" factory is rarely needed in test. Instead, "user_with_followers" and "user_following_some_ones" are often used.
factory :user do
sequence(:name) { |n| "Person #{n}" }
sequence(:email) { |n| "person_#{n}#example.com"}
password "foobar"
password_confirmation "foobar"
factory :user_with_followers do
ignore do
followers_count 5
end
after_create do |user, evaluator|
followers = FactoryGirl.create_list(:user, evaluator.followers_count)
followers.each do |follower|
follower.follow(user) # Suppose you have a "follow()" method in User
end
end
factory :user_following_some_ones do
# Do the similar
end
end
# Use
FactoryGirl.create :user_with_followers
use association
factory :relationship do |r| # 'r' is how you call relationship in the block
...
r.association :followed #relationship is associated with followed user
#(i'm not sure how your application is set up,
#so you'll have to do this as best makes sense.
#is followed an attribute of user?
#then it would look like `r.association :user`
f.association :follower #same here
end
In the more recent versions of FactoryGirl, you should be able to do this:
factory :relationship do
association :followed, :factory => :user
association :follower, :factory => :user
end
What each of those two association lines does is set up a user instance (using your :user factory), and then assign to followed or follower of the current relationship instance.
Note that you need to specify the factory unless the association name and factory name are the same.
Update:
When creating the Relationship, specify :followed or :follower (whichever is applicable to you). Otherwise, it creates new user records for each of those and uses them.
FactoryGirl.create(:relationship, :followed => #user)

has_one relation with validates_presence_of and the latest factory_girl

I am facing the same problem as the question here. The post is quite outdated. I was wondering how to do the same thing. My factory is:
FactoryGirl.define do
factory :user do
sequence(:email) {|n| "email#{n}#factory.com" }
password "foobar"
password_confirmation { |u| u.password }
profile
end
end
But FactoryGirl.create(:user) fails because of a validation error in the profile model with the user being blank.
What I would do is to use the after_create. This ensures it only creates profile after it creates user.
factory :user do
sequence(:email) {|n| "email#{n}#factory.com" }
password "foobar"
password_confirmation { |u| u.password }
after_create do |user|
FactoryGirl.create(:profile, :user => user)
end
end
You can call Factory(:user) afterward.

Resources