views:

43

answers:

3

Please help me get the include right.

Poem 
  has_many :awards
  has_one  :overall_ranking

Award
  belongs_to :poem
  # before
  # has_one :overall_ranking, :foreign_key => :poem_id 
  ## SOLUTION
  # after
  has_one :overall_ranking, :foreign_key => :poem_id, :primary_key => :poem_id

OverallRanking
  belongs_to :poem

update: Award.all(:include => [:overall_ranking]) # works with SOLUTION

Please note that I cannot depend on Poem#id as users may delete the poem, but if it's a winner, I make a copy within Award, so I must depend only on Award#poem_id Thank you!

A: 

You might want to give some more information but I hope this helps:

You might want to try joins.

For example:

Award.all(:joins => :overall_ranking, :conditions => ['some_attribute_from_overall_ranking=?', true])

So this will find awards and include the overall_ranking.

Sam
In Award.all I need the poem_id for the record it joins. I don't know how to do that.
Award.all(:joins => :overall_ranking, :conditions => ["poem_id = ?", self.poem_id]) ???
Award.all(:joins => "LEFT JOIN `overall_rankings` ON awards.poem_id = overall_rankings.poem_id") ???
Award.all(:joins => "LEFT JOIN overall_rankings as overall_ranking ON awards.poem_id = overall_rankings.poem_id") ???
A: 

There is some confusion for me.

Award
  belongs_to :poem
  has_one :overall_ranking, :foreign_key => :poem_id

Here you are using the same id for both relation. This means that you try to retrieve the overall ranking with the poem id. If I translate to sql you say something like:

overall_ranking.id = poem_id

I think this is wrong.

If you like to have the same overall_ranking for award and poem you can write something like this:

Award.rb
  belongs_to :poem
  has_one :overall_ranking, :through=>:poem

You can include like

Award.all(:include => [:overall_ranking])
or nested
Award.all(:include => [{:poem=>:overall_ranking}])

Update

1.Your has one association is set up incorrectly.

Please see: http://blog.hasmanythrough.com/2007/1/15/basic-rails-association-cardinality

Award
  belongs_to :poem
  belongs_to :overall_ranking, :foreign_key => :poem_id

OverallRanking
  belongs_to :poem
  has_one :award

You always should have belongs_to at the model where you store the referencing id. 2. But this not resolves your problem in your logic. With this you will still has association between Award#poem_id = OverallRanking#id. You should have Award#poem_id = OverallRanking#poem_id.

I suggest to add overall_ranking_id to Award and things become much cleaner.

dombesz
see edit above. I can't depend on Poem#id because Award is a separate copy just using the poem_id. Award makes a copy in case user deletes the poem (so I can keep the award visible). thankyou
A: 

Your problem is that:

has_one :overall_ranking, :foreign_key => :poem_id

means that Award has one OverallRanking and that the ID of Award in has_one relation is in column poem_id, i.e. your logic is wrong.

It would make more sense if you would just use:

@award.poem.overall_rating

Or in find:

Award.all(:include => [:poem => {:overall_ranking}])
Slobodan Kovacevic
please see edits, I can't depend on Poem#id
Hm. You can then specify :primary_key option which will tell Rails what attribute from Award you want to use for relation. For example: has_one :overall_ranking, :foreign_key => :poem_id, :primary_key => :poem_id
Slobodan Kovacevic
That's it, thank you :D
Now the original find works: Award.all(:include => :overall_ranking)