Using :through to get grandchildren objects

I cant seem to use :through to get the grandchildren objects when the
intermedetiate uses a has_one relationship with the grandchild model.

E.g.

class User < ActiveRecord::Base
has_many :sentences
has_many :corrections, :through => :sentences
end

class Sentence < ActiveRecord::Base
belongs_to :user
has_one :correction
end

class Correction < ActiveRecord::Base
belongs_to :sentence
end

I want to do User.corrections

but unfortunately that doesnt work. I get

ActiveRecord::HasManyThroughSourceAssociationMacroError: Invalid source
reflection macro :has_one for has_many :corrections, :through =>
:sentences. Use :source to specify the source reflection.

but if i remove the has_one and replace it with has_many like so

class Sentence < ActiveRecord::Base
belongs_to :user
has_many :corrections #previously has_one
end

then It works. The problem is I dont want to specify has_many because
there will only be one correction for a sentence.

How do i achieve what I want, namely to be able to access all the
corrections for a given user

Adam A. wrote:

class Sentence < ActiveRecord::Base
belongs_to :user
has_many :corrections #previously has_one
end

then It works. The problem is I dont want to specify has_many because
there will only be one correction for a sentence.

So could you not use the has_many abilities of the framework (and
achieve one of your goals) and enforce in your model your idea of a
single correction per sentence (achieving your other goal)?

It might be the simplest solution.

Ar Chron wrote:

Adam A. wrote:

class Sentence < ActiveRecord::Base
belongs_to :user
has_many :corrections #previously has_one
end

then It works. The problem is I dont want to specify has_many because
there will only be one correction for a sentence.

So could you not use the has_many abilities of the framework (and
achieve one of your goals) and enforce in your model your idea of a
single correction per sentence (achieving your other goal)?

It might be the simplest solution.

That’s a pretty bad idea. has_one is a little smelly, but it’s there,
and it should work with :through. Better to solve the problem than to
kludge around the framework.

Best,
–Â
Marnen Laibow-Koser
http://www.marnen.org
[email protected]

thanks guys for the replies.

I considered Ars suggestion but for the same reason as Marnen posted it
doesnt sit right.

But the problem is I created a new test project just to test the above
syntax out and its failing. We all make mistakes and blame the framework
but this time i honestly cant figure out the source of this problem. Im
starting to think that this is simply not possible in rails when you
have a has_one in the middle.

Can anyone confirm if this is a limitation of the framework?

Adam A. wrote:

Can anyone confirm if this is a limitation of the framework?

anyone???

How do you expect an answer to that if you haven’t told us what versions
of Ruby and Rails you’re using?

Best,

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

Marnen Laibow-Koser wrote:

Ar Chron wrote:

It might be the simplest solution.

That’s a pretty bad idea. has_one is a little smelly, but it’s there,
and it should work with :through. Better to solve the problem than to
kludge around the framework.

True, but I guess it depends on which ‘smell’ you find least
disagreeable… hence the ‘might be’.

If I had to have to working today, I’d work around the issue, and queue
up the issue for analysis. If I had time to research, I’d dive into the
framework code.

But that choice is very situational.

Can anyone confirm if this is a limitation of the framework?

anyone???

ahh sorry my bad. Im using rails 2.3.2 and ruby v1.87

On 15 June 2010 13:46, Adam A. [email protected] wrote:

Can anyone confirm if this is a limitation of the framework?

anyone???

You said in your first post that it didn’t work trying to do a
:though on a :has_one. So as far as I can see you have three choices:

  1. Fudge it with a :has_many that you manually check only has one
    associated - messy, as Marnen pointed out.

  2. Add the method I suggested to do the collect yourself (I default
    to using .inject, which is quite verbose… you could do the same
    thing with .map, which would remove the references to ‘memo’). If the
    functionality was in Rails, it would be doing something similar in
    the background…

  3. Patch Rails yourself to support going through a :has_one - look
    at the source of :has_many and see what it’s missing.

Personally, I’d do what I suggested (well, I would wouldn’t I! :wink: as
you can’t expect the framework to do everything for you, and helpers
like :through only come about when loads of people need to do the same
thing frequently.

On 15 June 2010 14:12, Marnen Laibow-Koser [email protected] wrote:

Adam A. wrote:

Can anyone confirm if this is a limitation of the framework?

anyone???

How do you expect an answer to that if you haven’t told us what versions
of Ruby and Rails you’re using?

I can confirm I get the same error trying to do a :has_many :through
on a :has_one “grandchild” in Rails 2.3.5 and Ruby 1.8.7

Like I said, I don’t think it’s a “problem” - it’s just not something
that anyone’s wanted enough (or at all) to be implemented. With the
amount of time you’ve probably spent stressing about it, you could
have written your own collection method a dozen times or more!

On 13 June 2010 15:25, Adam A. [email protected] wrote:

How do i achieve what I want, namely to be able to access all the
corrections for a given user

Create a method on User called “corrections” and collect up the user’s
sentences’ corrections.

class User < ActiveRecord::Base
has_many :sentences

def corrections
  sentences.inject([]) { |memo, sentence| memo <<

sentence.corrections }.flatten.compact
end
end

http://ruby-doc.org/core/classes/Enumerable.html#M003140

On Jun 15, 2:19 pm, Michael P. [email protected] wrote:

I can confirm I get the same error trying to do a :has_many :through
on a :has_one “grandchild” in Rails 2.3.5 and Ruby 1.8.7

Although this commit

(which would have made it into rails 2.3) claims otherwise

Fred

On 15 June 2010 14:23, Frederick C. [email protected]
wrote:

I can confirm I get the same error trying to do a :has_many :through
on a :has_one “grandchild” in Rails 2.3.5 and Ruby 1.8.7

Although this commit Enable has_many :through for going through a has_one association on t… · rails/rails@b763858 · GitHub
(which would have made it into rails 2.3) claims otherwise

Hrmm… I think curiosity will get me to check I wasn’t running an
old version… could’ve sworn the project I checked it on was 2.3.5…
:-/