has_one associations

108 views
Skip to first unread message

Danial Pearce

unread,
Aug 28, 2013, 11:17:26 PM8/28/13
to fabrica...@googlegroups.com
Since it seems fabricator will always create the associations first, I am wondering how to do a has_one relationship.

class Foo < ActiveRecord::Base
  has_one :bar
  has_one :baz
end

class Bar < ActiveRecord::Base
  belongs_to :foo
  validates_presence_of :foo
end

class Baz < ActiveRecord::Base
  belongs_to :foo
  validates_presence_of :foo
end

Fabricator(:foo)
Fabricator(:foo_with_bar, from: :foo) { bar }
Fabricator(:foo_with_baz, from: :foo) { baz }
Fabricator(:bar)
Fabricator(:baz)

Now it seems when I Fabricate(:foo_with_bar), it will give a validation error saying Bar.foo can't be null. How do I tell the :foo fabricator that it needs to pass itself through to the association in order for validations to pass? I generally don't interact directly with the :bar fabricator at all, so creating the fabrications from the side of the belongs_to at all times seems like I am missing something?

In my case, a Foo doesn't always have a Bar, but a Bar will always have a Foo. As you can tell from the validations. I want to be able to do

foo = Fabricate(:foo_with_bar)
bar = foo.bar # should be a Bar
baz = foo.baz # should be nil

I'm sure I'm just missing something, so if anyone feels the need to shoot me a link and say RTFM, I'm more than happy to.


regards,
Danial

Paul Elliott

unread,
Aug 29, 2013, 7:11:48 AM8/29/13
to fabrica...@googlegroups.com
When you are validating a has_one association like that, you won't be able to use the default expansion in the fabricators. Give this a try instead:

Fabricator(:foo_with_bar, from: :foo) do
  bar { Fabricate.build(:bar) }
end

-- Paul

--
You received this message because you are subscribed to the Google Groups "fabrication" group.
To unsubscribe from this group and stop receiving emails from it, send an email to fabricationge...@googlegroups.com.
For more options, visit https://groups.google.com/groups/opt_out.

Danial Pearce

unread,
Aug 29, 2013, 8:58:09 AM8/29/13
to fabrica...@googlegroups.com
Thanks for the response Paul. Your suggestion seems to have worked. I
had a work around in place like so:

Fabricator(:foo_with_bar) do
after_build do |foo|
foo.bar = Fabricate(:bar)
end
end

Which is kind of ugly and I knew there must've been a better way, I
just couldn't find it in any docs.

Your comment about "validating a has_one association like that"
confused me somewhat. I assume you meant validating the belongs_to
since that's where the validation is, but I would have thought (hoped)
that is pretty common practice?

I did hit another snag, but will create another thread as it is unrelated.


Thanks again.
Danial

Paul Elliott

unread,
Aug 29, 2013, 9:13:00 AM8/29/13
to fabrica...@googlegroups.com
I don't typically validate belongs_to associations because it tends to be more trouble than the value it provides. In most cases, child records can't be created in the UI without the knowledge of the parent. If you are handling multi-tenancy in your app, you should be creating records like this, in which case the validation is irrelevant:

foo.bars.create(params)

-- Paul

Reply all
Reply to author
Forward
0 new messages