0

I have a Parent who has many Children, but only one Firstborn. The Firstborn is a Child with a related ChildType of "firstborn".

class Parent
  has_many :children
  has_one :firstborn, -> { includes(:child_type).references(:child_type).where("child_type.name = ?", "firstborn") }, class_name: "Child"
end

class Child
  belongs_to :parent
  belongs_to :child_type
end

class ChildType
  has_many :children
end

The following code does not work:

parent = Parent.find(1)      # => <parent object>
firstborn = parent.firstborn # => nil

The end goal is being able to retrieve all Parents and Firstborn children in 1 query.

parents_and_firstborn = Parent.includes(:firstborn)

I'm looking for a solution that only executes 1 query and retrieves the Parent and related Firstborn children.

I've reviewed the Rails 4.0.2 API docs about has_one, but none of their examples span across multiple tables like what I'm trying to do.

Update: 2014-10-16 14:40

The following "works" but I don't know why:

parent = Parent.includes(:firstborn).find(1) # => <parent with firstborn>

Why can I not retrieve the firstborn AFTER I have retrieved the Parent, but if I includes(...) it in the original query it returns it?

Solution: 2014-10-16 14:50

I had an attr_accessor :firstborn still stuck in the Parent model from previous attempts as solving this problem. When I removed that unused code, the has_one :firstborn ... code worked as expected.

Dan L
  • 4,319
  • 5
  • 41
  • 74

1 Answers1

1

That looks correct(ish) as is, you should debug the SQL being executed.

I'd actually question the merit of the ChildType table from what I see here. You schema seems overly complicated. Why don't you use a first_born bool?

James Daniels
  • 6,883
  • 4
  • 24
  • 28
  • I would love to use an alternate schema design...however, I'm working with a legacy system and I have no ability to change it. Trust me, I've tried for a few months because of this issue and many, many others. For the particular issue, there will be multiple ChildTypes that I may need to query/filter on. – Dan L Oct 16 '14 at 18:32
  • If you show the SQL being returned on both cases; we might have better luck helping you debug. – James Daniels Oct 16 '14 at 18:45
  • Oh...I found the problem. I feel stupid now! While I was working on this problem, I had created an `attr_accessor :firstborn` before I decided to go with a `has_one` association. That accessor method was what was returning `nil`. Once I removed that, the above code actually did work as expected. I hate legacy systems! – Dan L Oct 16 '14 at 18:51
  • Ooof! Yay rubber ducking. Good luck with your legacy system; I've handled a couple of those before, they can be frustrating. – James Daniels Oct 16 '14 at 18:53