views:

477

answers:

3

I have such angry associations: financings >- events >- subprograms >- programs. I want to get acces to last_financings from programs through all of them so code is:

class Fcp < Program
  has_many :fcp_subprograms,
           :foreign_key => 'parent_id'
  has_many :subprogram_last_actual_financings,
           :through => :fcp_subprograms,
           :source => :last_actual_financings

class FcpSubprogram < Program
  belongs_to :fcp,
             :class_name => 'Fcp',
             :foreign_key => 'parent_id'

  has_many :events,
           :foreign_key => 'fcp_id'

  has_many :last_actual_financings,
           :through => :events,
           :source => :last_actual_financings

class Event < ActiveRecord::Base
  belongs_to :fcp,
             :class_name => 'Fcp',
             :foreign_key => 'fcp_id'
  belongs_to :fcp_subprogram,
             :class_name => 'FcpSubprogram',
             :foreign_key => 'fcp_id'

  has_many :last_actual_financings,
           :class_name => 'ActualFinancing',
           :order => 'date DESC',
           :limit => 1

So when I want to access to subprogram_last_actual_financings in after_initialize function I get this error

Invalid source reflection macro :has_many :through for has_many :subprogram_last_actual_financings, :through => :fcp_subprograms.  Use :source to specify the source reflection.

but I have :source option in my associations. What am I doing wrong?

A: 

This seems like a really awkward way of doing this... I'd rather make a virtual accessor in Program that calls something like this:

self.subprograms.first.events.first.financings.first(:order => 'date DESC')
dvyjones
But I need last financing for ALL the events in ALL the subprograms of program to sum it then. Finacing model acts like history of how financing changes through date periods. So really importrant only last by date financing. To calculate financing of a program I should sum last financings of all program's events and sum last financings of all events of all subprograms. Something like that
Antiarchitect
+2  A: 

The error you get is about source_reflection is an invalid association, because source for has_many through must be belongs_to, has_one or has_many without through option. So you can't use :last_actual_financings as a source.

Sergio Cambra
You can try nested_has_many_through plugin http://github.com/ianwhite/nested_has_many_throughUse rails-2.3 branch, although it's experimental. I haven't tried it.Or you can use finder_sql option for has_many
Sergio Cambra
Interesting plugin! I have to give it a try
klew
Thanks for your advice very much!
Antiarchitect
+1  A: 

As far as I remember you can't make association with double (or more) :through. The only thing you can do is write your own sql queries.

Here is my example how to do it:

class Person
  ...
  has_many :teams, :finder_sql =>
    'SELECT DISTINCT teams.* FROM teams
        INNER JOIN team_roles ON teams.id = team_roles.team_id
        INNER JOIN team_members ON team_roles.id = team_members.role_id
        WHERE ((team_members.person_id = #{id}))'

  # other standard associations
  has_many :team_members
  has_many :team_roles,
    :through => :team_members
  # and I couldn't do:
  # has_many :teams, :through => :team_roles

This is for relation Person -> has_many -> team_members -> has_many -> team_roles -> has_one - team.

Hope it helps.

klew
Thanks for your advice!
Antiarchitect