factory_girl create vs build and associations - ruby-on-rails

I am having some trouble with factory_girl's associations:
Factory.define :account do |f|
f.sequence(:email) {|n| "john#{n}#example.com" }
f.password "secret"
f.confirmed_at 2.days.ago.to_s(:db)
f.name "John Doe"
f.seller false
f.admin false
end
Factory.define :request do |f|
f.association :account
f.message 'Test message.'
end
And here's the problem:
When I do a = Factory(:request), a.account => nil but when I do a = Factory.build(:request), a.account is correct.
Any idea why this might be ?
Thanks

Factory(:request) calls for default strategy, did you changed that somewhere?

Related

NoMethodError: undefined method `to_sym' for {:factory=>:user}:Hash

I get an error when I call create on the character factory
factory :user do |f|
f.sequence(:email) { |n| "foo#{n}#example.com" }
f.password "password"
end
factory :character do |f|
f.name "testcharone"
f.race "human"
after(:create) { |character| character.init("fighter")}
association factory: :user
end
Error:
NoMethodError:
undefined method `to_sym' for {:factory=>:user}:Hash
Can anyone see what's wrong?
This test took 16 minutes to complete, while the others, which are similiar took between 5-10 minutes
describe Character do
let(:character) { FactoryGirl.create :character}
describe "#add_units" do
context "when unit doesnt exist beforehand" do
it "it create a new member" do
expect(character.owns.count).to eq(0)
character.add_units("character", "Archer" => 1)
expect(character.owns.count).to eq(1)
expect(character.owns.first.amount).to eq(1)
end
end
In factory :character,
Replace
association factory: :user
With
association :user
You have to pass only the factory name i.e., :user in this case and not a hash factory: :user
You facotry should be as like below
Hope you should ahave a factory for user as well
factory :character do |f|
f.name "testcharone"
f.race "human"
f.association :author, factory: :user
after(:create) { |character| character.init("fighter")}
end
or
factory :character do
name "testcharone"
race "human"
association :user
after(:create) { |character| character.init("fighter")}
end

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)) )

Rails 3 Validations - Association Properties, RSpec, and Factory Girl

I'm trying to write a validation class in rails 3 that will check for the presence of at least one associated object that has a particular property value.
In my scenario, an Account can have many Users. The User model has a "Role" string field. An account must have at least one User with a Role that equals "admin".
The following code is breaking during my testing (I'm using rspec & Factory Girl). When the tests are executed, the account_id is returning as null.
Here is the model:
class Account < ActiveRecord::Base
validates :name, :presence => true, :uniqueness => true
validate :has_one_admin
has_many :users
attr_accessible :name
private
def has_one_admin
User.where(:role => "admin", :account_id => self.id).count > 0
end
end
Here is the error being thrown by rspec:
Error message being thrown: Failure/Error: #account = Factory(:account_with_admin)
ActiveRecord::StatementInvalid:
SQLite3::SQLException: no such column: users.account_id: SELECT COUNT(*) FROM "users" WHERE "users"."role" = 'admin' AND "users"."account_id" IS NULL
Here is the RSpec test:
require 'spec_helper'
describe Team do
# - Removed -
# before(:each) do
# #account = Factory(:account)
# #attr = { :name => "Testing Team"}
# end
# Modified after discussion...
before(:each) do
#user = Factory(:user)
#act_attr = { :name => "My Account",
:users => #user }
#account = Account.new(#act_attr)
#attr = { :name => "Testing Team"}
end
# End of modification
it "must have a name" do
no_name_team = Team.new(#attr.merge(:name => ""))
no_name_team.should_not be_valid
end ...
And finally, my factory file:
Factory.define :admin, :class => User do |f|
f.email 'admin#admin.com'
f.password 'password'
f.role 'admin'
end
Factory.define :team, :class => Team do |f|
f.name 'Testing Team'
end
Factory.define :account, :class => Account do |f|
f.name 'Testing Account'
end
Factory.define :account_with_admin, :parent => :account do |f|
f.after_create { |a| Factory(:admin, :account => a) }
end
My assumption is that I'm jumping ahead of the persisting of the object somewhere but I'm just not sure where. Thanks for any help / direction!

Rspec + Factory Girl First Example works, 2nd+ do not

I have an spec like so:
require 'spec_helper'
describe IncomingMailsController do
include Devise::TestHelpers
before(:each) do
#user = Factory.create(:user)
#user1 = Factory.create(:user)
#group = Factory(:group)
#perm1 = Factory.create(:permission, :user => #user)
#perm2 = Factory.create(:permission, :user => #user1)
end
it "xxxxx case 1" do
....
end
it "xxxxx case 2" do
....
end
The first case 1, works fine but then the 2nd fails with:
Failure/Error: #perm1 = Factory.create(:permission, :user => #user)
RuntimeError:
Called id for nil, which would mistakenly be 4 -- if you really wanted the id of nil, use object_id
# ./spec/factories.rb:23
Does the before each run fresh for each it block?
factories.rb looks like:
require 'factory_girl'
Factory.define :user do |f|
f.sequence(:fname) { |n| "fname#{n}" }
f.sequence(:lname) { |n| "lname#{n}" }
f.sequence(:email) { |n| "email#{n}#google.com" }
f.password "password"
f.password_confirmation { |u| u.password }
f.invitation_code "dmbsrv82811"
end
Factory.define :group do |f|
f.name "myGroup"
f.sequence(:private_email) { |n| "myGroup#{n}" }
end
Factory.define :permission do |f|
f.role_id 1
f.group_id do
(Group.find_by_name('myGroup')).id
end
f.creator_id do
(User.find_by_fname('fname1')).id
end
end
Thanks
On line 23 of factories.rb you have
(User.find_by_fname('fname1')).id
This is hardcoded to find fname1. However, your factory uses a sequence to define fname:
f.sequence(:fname) { |n| "fname#{n}" }
This means that in the second spec, the value for fname will be fname2, not fname1. This is because sequences aren't reset between different specs.
All of this means that when you call User.find_by_fname, it can't find a user with fname1 (only fname2), so it returns nil, which is why you get the called id for nil error.
-- Edit --
Are you doing anything with the user attribute you pass in to the permission factory (for eg with Factory.create(:permission, :user => #user))? If not, I'd change it to something like
Factory.create(:permission, :creator => #user)
Note: if you don't have Permission#creator setup as an association with User you'll need to rather do
Factory.create(:permission, :creator_id => #user.id)
On a similar vein, you might want to define your factory more along the lines of
Factory.define :permission do |f|
f.role_id 1
f.association :group, :factory => :group
f.association :creator, :factory => :user
end
If your associations are setup correctly, there's no need to worry about the ids, the association does the Right Thing for you.

Dependent Attributes in Factory Girl

Seems like I should have been able to find an obvious answer to this problem after a few hours of Googling and testing.
I want to be able to set caredate.user_id => provider.user_id within the caredate factory.
Test Error:
ActiveRecord::RecordInvalid:
Validation failed: User must be same
as provider user
I have an ActiveRecord validation which works when tested via the browser:
class Caredate < ActiveRecord::Base //works fine when testing via browser
belongs_to :user
belongs_to :provider
validates_presence_of :user_id
validates_presence_of :provider_id
validate :user_must_be_same_as_provider_user
def user_must_be_same_as_provider_user
errors.add(:user_id, "must be same as provider user") unless self.user_id == self.provider.user_id
end
end
//factories.rb
Factory.define :user do |f|
f.password "test1234"
f.sequence(:email) { |n| "foo#{n}#example.com" }
end
Factory.define :caredate do |f|
f.association :provider
**f.user_id { Provider.find_by_id(provider_id).user_id } //FAILS HERE**
end
Factory.define :provider do |f|
f.association :user
end
My apologies if this has been answered previously; I tried several different options and couldn't get it to work.
Update: This passes validation, so I'm getting closer. I could hack with a random number.
Factory.define :caredate do |f|
f.association :user, :id => 779
f.association :provider, :user_id => 779
end
Factory.define :caredate do |f|
provider = Factory.create(:provider)
f.provider provider
f.user provider.user
end
Try setting the user_id in after_create or after_build:
Factory.define :caredate do |f|
f.after_create { |caredate| caredate.user_id = caredate.provider.user_id }
end

Resources