Has_many Association in FactoryGirl - ruby-on-rails

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 }
. . .

Related

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

FactoryGirl Validation failed: Email has already been taken

I have next code:
My users_controller_test.rb:
require 'test_helper'
class Api::Be::UsersControllerTest < ActionController::TestCase
setup do
admin = FactoryGirl.create :admin
store = FactoryGirl.create(:store, admin: admin)
store.ug_default = UgDefault.new
store.save
customer = FactoryGirl.create :customer
customer.store_id = store.id
customer.save
end
test "should show user" do
get :show, store_id: store.id, u: admin.u_token
assert_response :success
json = response.body
data = JSON.parse(json)
assert_equal 'ok', data['status']
end
end
In my sequences:
sequence :email do |n|
"email-#{n}#example.com"
end
And my factories:
FactoryGirl.define do
factory :admin do
end
end
And
FactoryGirl.define do
factory :store do
admin
name {generate :string}
subdomain {generate :string}
linked_domain {generate :string}
end
end
And
FactoryGirl.define do
factory :customer do
end
end
And
FactoryGirl.define do
factory :user do
first_name {generate :string}
last_name {generate :string}
email {generate :email}
password_digest {generate :password_digest}
login_attempts 1
company_name {generate :string}
phone {generate :string}
u_token 'u'
end
end
Admin and Customer inherited from User.
Now I have Validation failed: Email has already been taken error in line customer = FactoryGirl.create :customer. I've tried to clean database. rake db:test:prepare didn't work too.
Can it be that your :admin and :customer factories does not inherit from your :user factory? Does it work if your :admin and :customer factories are defined like this?
FactoryGirl.define do
factory :admin, parent: :user do
end
factory :customer, parent: :user do
end
end

FactoryGirl How to add several objects with different roles

class Ability
include CanCan::Ability
def initialize(user)
user ||= User.new # guest user
if user.has_role? :student
can :create, Atendimento
end
if user.has_role? :professor
can :create, Atendimento
end
if user.has_role? :administrative
can [:read, :create], [Atendimento]
can [:edit, :update], Atendimento
can :manage, [Type, Place]
end
if user.has_role? :admin
can :manage, :all
end
end
end
and my factory
FactoryGirl.define do
factory :user do |f|
f.name "Alessandro"
f.username "alessandrocb"
f.matricula "123456789"
f.password "123456789"
f.password_confirmation "123456789"
f.after(:create) {|user| user.add_role(:student)}
end
I need those mocks receive all roles , but now I can only student role
my test with rspec
subject(:ability){ Ability.new(user) }
let(:user){ nil }
context "when is an User" do
let(:user) { FactoryGirl.create(:user) }
what is happening is this: I can only test with rspec with only 1 paper, but would like to test with all the cancan, I need to create the factory with all these possibilities for different roles
First solution
FactoryGirl.define do
factory :user do
name "Alessandro"
username "alessandrocb"
(...)
trait :student do
after(:create) {|user| user.add_role(:student)}
end
trait :professor do
after(:create) {|user| user.add_role(:professor)}
end
trait :administrative do
after(:create) {|user| user.add_role(:administrative)}
end
trait :admin do
after(:create) {|user| user.add_role(:admin)}
end
end
end
You can then use and combine these traits like this:
# Create a student
create :user, :student
# Create a user who is both professor and admin
create :user, :professor, :admin
Second solution
FactoryGirl.define do
factory :user do
name "Alessandro"
username "alessandrocb"
(...)
ignore do
role
end
after(:create) do |user, params|
user.add_role(params.role) if params.role
end
end
end
And then:
# Create a student
create :user, role: :student
Note that the second solution does not allow you to combine roles as it is. But you could use an array to achieve this.
I recently ran into a similar issue. Here's my users factory:
FactoryGirl.define do
sequence :email do |n|
"user#{n}#example.com"
end
factory :user do
email
password 'password'
factory :admin_user do
role 'administrator'
end
factory :support_user do
role 'support'
end
factory :editor_user do
role 'editor'
end
factory :sales_user do
role 'sales'
end
factory :author_user do
role 'author'
end
factory :guest_user do
role 'guest'
end
end
end
From there I can just call the relevant factory for a spec:
create(:editor_user)
Or, depending on your User model and it's attendant properties, you could also build factories like:
create(:user, role: 'guest') # my User model has a properly called 'role'
I have 3 different users in my project: default, merchant, admin.
I have one file that handles the conditions. Note: this is FactoryBot and specifically factory bot rails. I am also using the gem Faker.
edit: the numbered roles are using enum, which converts the number in a string according to an array I defined. More on enums: https://naturaily.com/blog/ruby-on-rails-enum
factories/user.rb
// factories/user.rb
FactoryBot.define do
factory :user do
name { Faker::Name.first_name }
street_address { Faker::Address.street_address }
city { Faker::Address.city }
state { Faker::Address.state }
zip { Faker::Address.zip }
email { Faker::Internet.email }
password { Faker::Internet.password }
trait :default_user do
role { 0 }
end
trait :admin_user do
role { 1 }
end
trait :merchant_user do
role { 2 }
end
end
end
spec file
// a spec file
RSpec.describe 'User logging in' do
let(:user) { create(:user, :default_user) }
let(:admin) { create(:user, :admin_user) }
[...]
end

Where do I confirm user created with FactoryGirl?

Using rails, devise, rspec & factorygirl:
Trying to create some tests for my site. I'm using the confirmable model for devise so when I create a user using FactoryGirl, the user isn't confirmed.
This is my factories.rb:
FactoryGirl.define do
factory :user do
full_name "Aren Admin"
email "aren#example.com"
password "arenaren"
password_confirmation "arenaren"
role_id ADMIN
end
end
And this is my rspec test file:
require 'spec_helper'
describe "Admin pages" do
subject { page }
describe "home page" do
let(:user) { FactoryGirl.create(:user) }
before { visit admin_home_path }
it { should have_content("#{ROLE_TYPES[user.role_id]}") }
end
end
I'm getting an error because the user is not confirmed. By searching around I'm pretty sure I need to use the method 'confirm!' and that it belongs in the factories.rb file, but I'm not sure where to put it.
You could also set the confirmed_at attribute as follows. Works for me:
FactoryGirl.define do
factory :user do
full_name "Aren Admin"
email "aren#example.com"
password "arenaren"
password_confirmation "arenaren"
role_id ADMIN
confirmed_at Time.now
end
end
Better yet, do the following (then you don't need to create a before filter for every test suite)
Factory.define :confirmed_user, :parent => :user do |f|
f.after_create { |user| user.confirm! }
end
found here:
https://stackoverflow.com/a/4770075/1153149
Edit to add non-deprecated syntax
FactoryGirl.define do |f|
#Other factory definitions
factory :confirmed_user, :parent => :user do
after_create { |user| user.confirm! }
end
end
Edit 01/27 To Update Syntax Again
FactoryGirl.define do
#Other factory definitions
factory :confirmed_user, :parent => :user do
after(:create) { |user| user.confirm! }
end
end
Try user.confirm! in your before block
found here
This is the factory that worked for me
FactoryGirl.define do
factory :user do
sequence :email do |n|
"address#{n}#example.com"
end
sequence :password do |n|
"password#{n}"
end
factory :confirmed_user do
before(:create) {|user| user.skip_confirmation! }
end
end
end
Put the Devise confirmable logic in the after(:build) callback...
FactoryGirl.define do
factory :user do
after(:build) do |u|
u.confirm!
u.skip_confirmation_notification!
end
...
end
For me, putting confirm! or skip_confirmation! in the after(:create) block caused validation errors on the email parameter and did not work.
Add this line to your User factory definition:
before(:create) { |user| user.skip_confirmation! }
You should call skip_confirmation! before create so this is persisted on the user.
before(:create) do |user|
user.skip_confirmation!
end
2023
Does not work:
before(:create, &:skip_confirmation!)
Works:
after(:build, &:skip_confirmation!)

Rails 3 - Factory girl and sequence for belongs_to table

I have 2 models - User and Teacher. Teacher belongs_to User, User has Teacher.
So, i use Factory girl gem:
Factory.define :user do |user|
user.user_login "Another User"
user.user_role "admin"
user.password "foobar"
end
Factory.sequence :user_login do |n|
"person-#{n}"
end
Factory.define :teacher do |teacher|
...
teacher.user
end
I met problem and i don't understand how to solve that. When i create user via factory i can easily write:
#user = Factory( :user, :user_login => Factory.next(:user_login) )
And this creates user with inique login.
How can i do same thing for teacher? I tried that:
#teacher = Factory( :teacher, :user_login => Factory.next(:user_login) )
And it doesn't work.
You don't have to specify sequences separately and then pass them to another factory - you can use them inside factories like this:
Factory.define :user do |user|
# ...
user.sequence(:user_login) { |n| "person=#{n}" }
end
or shorter
Factory.define :user do
# ...
sequence(:user_login) { |n| "person=#{n}" }
end
Then, to association a user with teacher:
Factory.define :teacher do
association :user
end
Then you can just call
#teacher = Factory(:teacher)
which will automatically create the associated user with the next user_login in the sequence.
I solved that.
#teacher = Factory( :teacher,
:user => Factory(:user, :user_login => Factory.next(:user_login)) )

Resources