Ruby on Rails Monday, December 27, 2010

Phoenix Rising wrote in post #970888:
> Thank you for the reply, Colin. I should have been more descriptive,
> so let me elaborate:
>
> Say I have the following models and factories:
>
> # models
> class Game < ActiveRecord::Base
> validates :name, :presence => true, :uniqueness => true
> validates :url, :presence => true, :uniqueness => true
> end
>
> class Server < ActiveRecord::Base
> belongs_to :game
> validates :name, :presence => true
> validates :game, :presence => true
> end

Server belongs_to Game? Really? Are you sure? If so, why isn't there
a corresponding association on Game? What are you trying to model here?

>
> class Character < ActiveRecord::Base
> belongs_to :server # now we can chain character.server.game
> validates :name, :presence => true
> end
>
> # test/factories.rb
> Factory.define :game do |g|
> g.name "Foo"
> g.url "www.example.com"
> end
>
> Factory.define :server do |s|
> s.name "Bar"
> s.game { |x| x.association(:game) }
> end
>
> Factory.define :character do |c|
> c.name "Blah"
> c.server { |x| x.association(:server) }
> end

What's with all the constant data? Use Faker and/or sequences to
generate unique values.

>
> Now, let's say I want to call Factory(:character). It all gets set up
> and returned properly as it should. But let's say I have the
> following in my factories thereafter:
>
> Factory.define :character2 do |c|
> c.name "Bleh"
> c.server { |x| x.association(:server) }
> end

Again, I worry about :character2. Looks like you're trying to predefine
every record you need in your factory files -- that is, use them like
fixtures -- which is not how factories are supposed to work. The reason
you can define multiple factories for one class is so you can set up
several default configurations (say, ordinary user and admin user), not
so you can define every record in advance.

>
> Logically, I'd expect factory_girl to try to create the :server
> object, and if it fails, look for it in the database and set the
> assignment of that association to what comes out of the DB if
> something already exists. But it doesn't do that.

No, it doesn't. association *always* creates a new record. Of course,
you can override that by doing Factory :character, :server => @server.
But this is not like fixtures, where it retrieves an existing named
fixture. Nor would you want it to be; it would make factories less
flexible.

You can also use AR model methods to find the existing association
record you want.

> Instead, FG will
> cause an error in tests (not a failure, an actual error) that will say
> that the name and url are already taken. After shaking my fists in
> the air and pounding my head on the desk, I reply, "YES, I KNOW
> they're taken, that's because I want the association on an EXISTING
> OBJECT!"

...which is not what the association method does. Find the object and
use it explicitly.
>
> Am I just plain doing it wrong here? Any input you have would be
> appreciated. Thank you!

Yes, you are doing it wrong. You're trying to use factories like
fixtures, and (possibly as a result) you're misunderstanding the
semantics of the association method.

Best,
-- 
Marnen Laibow-Koser
http://www.marnen.org
marnen@marnen.org

Sent from my iPhone

--
Posted via http://www.ruby-forum.com/.

--
You received this message because you are subscribed to the Google Groups "Ruby on Rails: Talk" group.
To post to this group, send email to rubyonrails-talk@googlegroups.com.
To unsubscribe from this group, send email to rubyonrails-talk+unsubscribe@googlegroups.com.
For more options, visit this group at http://groups.google.com/group/rubyonrails-talk?hl=en.

No comments:

Post a Comment