Has_many :through over more than 3 tables?

Hi all,

This weekend I started coding my first Rails app. So far I’m really
liking it; in just 2 days my app is already taking pretty good shape.
However, I have a couple of questions regarding ActiveRecord that I
hope people can help me with.

I’m creating a ‘financial application’ where there are groups of users.
Within each group, the users can transfer money to other users in the
same group. Each transfer can involve an unspecified number of group
members. I use four models: Group, User, Entry and Transfer:

class Group < ActiveRecord::Base
has_many :users
end

class User < ActiveRecord::Base
belongs_to :group
has_many :entries
has_many :transfers, :through => :entries
end

class Entry < ActiveRecord::Base
belongs_to :user
belongs_to :transfer
end

class Transfer < ActiveRecord::Base
has_many :entries
has_many :users
end

In effect each transfer is linked to one group and a group can have
many transfers. I tried using has_many :through to link Group and
Transfer, but that does not seem to work. Is it at all possible to do
it this way? I could think of two other options to get the transfers
linked to a group:

  1. Use has_many :transfers with finder_sql set to a big ‘inner join’
    query
  2. Create a group_id field in the transfers table

I went with option 1 initially, because then I’m not storing redundant
information in my database. On the other hand, it feels like I’m
sacrificing a lot of Rails goodness this way, like being able to use
:order or pagination. What is the common way of solving this problem,
is there a third option perhaps?

Another question I have is when I list information about a transfer. I
would like to show for a transfer, how much each user paid or received.
This is very easy to do by using transfer.users and then for each user
I call user.entry. However, in this way I’m doing a lot of database
calls for each transfer. Since this is mostly a personal test
application, it doesn’t really need to scale, but it still feels a bit
wasteful to me. What do other people think?

Thanks very much,
Hencq

Well, after thinking about it some more, I found a different solution
that solves my problem. It feels a bit schizophrenic to answer my own
question, but hey, maybe it’s useful for someone else :wink:

To obtain the transfers that belong to a certain group I now do:
Transfer.find :all, :include {:entries => :user}, conditions =>
[“group_id = ?”, group.id]

where group is the instance of Group for which I want to find the
transfers.
This also solves the problem of the large amount of queries to display
a list of transfers, since this eager loads all the entries and there
associated user for the transfer.

cheers,
Hencq