Factory_girl question

I am still trying to wrap my head around FG… can someone explain me
why I
am seemingly having to reload an object to have access to the correct
association value which I updated since creating the object with FG.
Here is
an example (Factory below also):

@person = Factory(:person)
@person.addresses.size.should == 0
address = Factory(:address)
@person.add_address(address)
@person = Person.find(@person.id) # if I dont do this I get the old
value,
0, but if I reload I get the right value, 1.
@person.addresses.size.should == 1
@person.addresses[0].person_id.should == @person.id

Factory.define :person do |f|
f.first_name {“MyString”}
f.middle_name {“MyString”}
f.last_name {“MyString”}
end

Factory.define :address do |f|
f.person_id {1}
f.address {“MyString”}
f.zip {“94587”}
f.city {“MyString”}
f.state {“MyString”}
end

David K. wrote in post #968158:

I am still trying to wrap my head around FG…

What’s to wrap your head around? All it does is create an object with
some associations. If you’re finding it confusing, you’re most likely
overthinking it.

can someone explain me
why I
am seemingly having to reload an object to have access to the correct
association value which I updated since creating the object with FG.
Here is
an example (Factory below also):

@person = Factory(:person)
@person.addresses.size.should == 0
address = Factory(:address)
@person.add_address(address)

Does add_address save @person ?

Personally, I would do @person.addresses << address , which always seems
to do the right thing.

@person = Person.find(@person.id) # if I dont do this I get the old
value,
0, but if I reload I get the right value, 1.
@person.addresses.size.should == 1
@person.addresses[0].person_id.should == @person.id

You do know that, while this test is useful for getting to know Factory
Girl, it is of no use for an actual application, right? All it’s doing
is testing FG and AR functionality that’s already well tested.

Factory.define :person do |f|
f.first_name {“MyString”}
f.middle_name {“MyString”}
f.last_name {“MyString”}
end

Factory.define :address do |f|
f.person_id {1}
f.address {“MyString”}
f.zip {“94587”}
f.city {“MyString”}
f.state {“MyString”}
end

I don’t think you need to use blocks for constant values.

However, once you get FG working, I highly recommend using Faker to
generate the data.

Best,

Marnen Laibow-Koser
http://www.marnen.org
[email protected]

On Mon, Dec 13, 2010 at 4:51 PM, Marnen Laibow-Koser
[email protected]wrote:

association value which I updated since creating the object with FG.
Here is
an example (Factory below also):

@person = Factory(:person)
@person.addresses.size.should == 0
address = Factory(:address)
@person.add_address(address)

Does add_address save @person ?

No, the call does just save the new address. I pass it this way as I
want to
ensure the person object id gets attached to the new address.

You do know that, while this test is useful for getting to know Factory
Girl, it is of no use for an actual application, right? All it’s doing
is testing FG and AR functionality that’s already well tested.

Right… but when I start having a problem I write more test code, that
is
how I got here…

f.person_id {1}
f.address {“MyString”}
f.zip {“94587”}
f.city {“MyString”}
f.state {“MyString”}
end

I don’t think you need to use blocks for constant values.

Right, that was an oversight

However, once you get FG working, I highly recommend using Faker to
generate the data.

I 'll try it when I have a chance… thanks

David K. wrote in post #968171:

On Mon, Dec 13, 2010 at 4:51 PM, Marnen Laibow-Koser
[email protected]wrote:

association value which I updated since creating the object with FG.
Here is
an example (Factory below also):

@person = Factory(:person)
@person.addresses.size.should == 0
address = Factory(:address)
@person.add_address(address)

Does add_address save @person ?

No, the call does just save the new address.

So it’s not changing @person at all, which means that Rails has no way
of knowing that the association has changed. That’s probably why you’re
getting the results you are.

I pass it this way as I
want to
ensure the person object id gets attached to the new address.

@person.addresses << address does likewise, but I believe it does save
or reload @person.

Best,

Marnen Laibow-Koser
http://www.marnen.org
[email protected]

On Mon, Dec 13, 2010 at 5:07 PM, Marnen Laibow-Koser
[email protected]wrote:

address = Factory(:address)

Thank you, that makes a lot of sense. The fog is clearing.

I pass it this way as I
want to
ensure the person object id gets attached to the new address.

@person.addresses << address does likewise, but I believe it does save
or reload @person.

Right, at least in the past this has worked in Rails 2.

On Dec 13, 2:51pm, Marnen Laibow-Koser [email protected] wrote:

However, once you get FG working, I highly recommend using Faker to
generate the data.

Marnen, you consistently take Rails’ hallmark “opinionated software”
up a couple of orders of magnitude :wink: so I’m curious about your
opinion on FG vs Machinist. This isn’t flame bait; I really am curious
as I’m deliberating between the two. TIA.

Stan K. wrote in post #968201:

On Dec 13, 2:51pm, Marnen Laibow-Koser [email protected] wrote:

However, once you get FG working, I highly recommend using Faker to
generate the data.

Marnen, you consistently take Rails’ hallmark “opinionated software”
up a couple of orders of magnitude :wink:

I’m almost afraid to ask how you meant that… :slight_smile:

so I’m curious about your
opinion on FG vs Machinist. This isn’t flame bait; I really am curious
as I’m deliberating between the two. TIA.

I’ve been using Machinist for personal projects and Factory Girl at my
current job. I think I find Machinist friendlier, but the two libraries
are pretty close at this point.

Best,

Marnen Laibow-Koser
http://www.marnen.org
[email protected]

Sent from my iPhone

On Tue, Dec 14, 2010 at 9:43 AM, [email protected] <
[email protected]> wrote:

@person.addresses[0].person_id.should == @person.id
f.zip {“94587”}
f.association :person
@person = Factory(:person)

Because the second line will generate another, unneeded Person object.

Thanks… this helps

On Dec 13, 4:05pm, David K. [email protected] wrote:

@person = Factory(:person)
@person.addresses.size.should == 0
address = Factory(:address)
@person.add_address(address)
@person = Person.find(@person.id) # if I dont do this I get the old value,
0, but if I reload I get the right value, 1.
@person.addresses.size.should == 1
@person.addresses[0].person_id.should == @person.id

Factory.define :person do |f|
f.first_name {“MyString”}
f.middle_name {“MyString”}
f.last_name {“MyString”}
end

Factory.define :address do |f|
f.person_id {1}
f.address {“MyString”}
f.zip {“94587”}
f.city {“MyString”}
f.state {“MyString”}
end

Side note about FG usage: I was under the impression that this is
suboptimal for FG because now Factory(:address) generates and invalid
object unless you do something special. I traditionally write this as
like this:

Factory.define :address do |f|
f.association :person
f.address {“MyString”}
f.zip {“94587”}
f.city {“MyString”}
f.state {“MyString”}
end

This way if I want an address to test and I don’t care about it’s
person, then Factory(:address) gives me a valid item. And then if I
do care about the association then we do:

@person = Factory(:person)
@person.addresses.size.should == 0
@address = Factory(:address, :person => @person)
@person.address.size.should == 0
@person.reload.address.size.should == 1

Keep in mind that in this case you don’t want to do:

@person = Factory(:person)
@address = Factory(:address)
@person.addresses << @address

Because the second line will generate another, unneeded Person object.

\Peter

[email protected] wrote in post #968310:
[…]

Keep in mind that in this case you don’t want to do:

@person = Factory(:person)
@address = Factory(:address)
@person.addresses << @address

Because the second line will generate another, unneeded Person object.

Hold it. If there’s a habtm relationship between Person and Address,
then Addresses shouldn’t even have a person_id. OTOH, if there isn’t a
habtm relationship, then the << operation is unnecessary (and I think
it’s a syntax error).

So…which is it?

\Peter

Best,

Marnen Laibow-Koser
http://www.marnen.org
[email protected]

f.city {“MyString”}
f.state {“MyString”}
end

you pass a block like this if you need reevaluation like when using a
rand
function or faker, it makes no sense to do it with a fixed value

f.address ’ foo’ is the same as f.address { ‘foo’ }

the first and second address created will have the same value in both
cases

f.zip rand(1000) the first and second record created will have the same
value
f.zip { rand(1000) } each record will have a unique value

so you should add faker and then

f.city {Faker::Address.city}

will give you a differente city for each record

On Dec 14, 10:14am, Marnen Laibow-Koser [email protected] wrote:

Hold it. If there’s a habtm relationship between Person and Address,
then Addresses shouldn’t even have a person_id. OTOH, if there isn’t a
habtm relationship, then the << operation is unnecessary (and I think
it’s a syntax error).

So…which is it?

In his original example Address has a person_id field so I was
assuming a has_many relationship, not a HABTM. However, though I’d
want to reflect on it further, I’m pretty sure it doesn’t change
anything here as long as you deal with the relationship name
everywhere and not the ID fields; Rails will just do The Right Thing
™ and add/remove records in the join table appropriately.

The << is necessary in the second example to be comparable to his
original example where he wanted to create an @person object, then
create an @address object and have them linked; the @address at first
will point to a different Person object than @person, so using the <<
on the collection will add it (i.e. it will set person_id on @address
to @person.id). It does work BTW, I just tested it again in console
to be sure (and its listed at the top of the added methods here:
http://apidock.com/rails/ActiveRecord/Associations/ClassMethods/has_many,
and if we care about the HABTM here:
http://apidock.com/rails/ActiveRecord/Associations/ClassMethods/has_and_belongs_to_many).

I think maybe what you’re pointing out though, is that he could just
do:

@address = Factory(:address)

and then use @address.person?

If that’s adequate then that’s definitely cleaner (and quicker and
more robust). However, what I read from the OP is that he has a need
to create a Person object first, configured a specific way (although
he didn’t have any particular factory overrides, so maybe this is an
incorrect assumption?). ~After~ that object is created he needs an
Address that is linked to it. As such he either needs to 1) create
the Address object with a stub Person, then associate with the one he
wants afterwards (suboptimal, the usage of <<) or 2) pass in the
Person object to the Address factory to link at creation time
(preferred, AFAIK).

\Peter

[email protected] wrote in post #968602:

On Dec 14, 10:14am, Marnen Laibow-Koser [email protected] wrote:

Hold it. If there’s a habtm relationship between Person and Address,
then Addresses shouldn’t even have a person_id. OTOH, if there isn’t a
habtm relationship, then the << operation is unnecessary (and I think
it’s a syntax error).

So…which is it?

In his original example Address has a person_id field so I was
assuming a has_many relationship, not a HABTM.

Which means << is invalid, doesn’t it?

However, though I’d
want to reflect on it further, I’m pretty sure it doesn’t change
anything here as long as you deal with the relationship name
everywhere and not the ID fields; Rails will just do The Right Thing
™ and add/remove records in the join table appropriately.

It’s has_many, so there’s no join table.

[…]

I think maybe what you’re pointing out though, is that he could just
do:

@address = Factory(:address)

and then use @address.person?

No. That’s not at all what I’m pointing out.

If that’s adequate then that’s definitely cleaner (and quicker and
more robust). However, what I read from the OP is that he has a need
to create a Person object first, configured a specific way (although
he didn’t have any particular factory overrides, so maybe this is an
incorrect assumption?). ~After~ that object is created he needs an
Address that is linked to it. As such he either needs to 1) create
the Address object with a stub Person, then associate with the one he
wants afterwards (suboptimal, the usage of <<) or 2) pass in the
Person object to the Address factory to link at creation time
(preferred, AFAIK).

That’s correct.

Best,

Marnen Laibow-Koser
http://www.marnen.org
[email protected]

\Peter

On Dec 15, 9:40am, Marnen Laibow-Koser [email protected] wrote:

Which means << is invalid, doesn’t it?
Perhaps I’m not understanding what you mean when you say invalid? Do
you mean that it will generate an exception, or that it isn’t a good
way to solve the problem?

\Peter

[email protected] wrote in post #968626:

On Dec 15, 9:40am, Marnen Laibow-Koser [email protected] wrote:

Which means << is invalid, doesn’t it?
Perhaps I’m not understanding what you mean when you say invalid? Do
you mean that it will generate an exception, or that it isn’t a good
way to solve the problem?

I mean that << isn’t defined for has_many, but on reflection I realize I
was wrong. Just forget I said that. :smiley:

\Peter

Best,

Marnen Laibow-Koser
http://www.marnen.org
[email protected]