Associations between 3 models

Hi,

   I have this requirement where in the association needs to be between 3 models.

I want a User to select a Gift to be sent to a particular Destinations. For this I created a Model RequestForGift with foreign keys ( belongs_to ) to the User, Gift and Destination.Then I added the has_many relationships to each of the 3 Models to the other 2, but some how the usage of the association through the models is not comforting

class User < ActiveRecord::Base   has_many :RequestForGifts   has_many :Gifts, :through => :RequestForGifts, :uniq => true   has_many :Destinations, :through => :RequestForGifts, :uniq => true end

class Gift < ActiveRecord::Base   has_many :RequestForGifts   has_many :Users, :through => :RequestForGifts, :uniq => true   has_many :Destinations, :through => :RequestForGifts, :uniq => true end

class Destination < ActiveRecord::Base   has_many :RequestForGifts   has_many :Users, :through => :RequestForGifts, :uniq => true   has_many :Destinations, :through => :RequestForGifts, :uniq => true end

class RequestForGift < ActiveRecord::Base   belongs_to :Gift   belongs_to :User   belongs_to :Destination end

i.e. I am not able to find All the Gifts sent by a User to New Delhi, India

Basically i am looking for some code like 1) User.find(params[:id]).gifts.select( |g| { g.destination.name = 'New Delhi, India' } )

I know that the same can be achieved by using the RequestForGift directly :-

a) destination_id = Destination.find_by_name ( :first, 'New Delhi, India' ) RequestForGift.find ( :all, :conditions => [ 'destination_id = ? and user_id = ?', destination_id, params[:id] ] ).collect ( |r| r.gift ) or b) User.find(params[:id]).requestForGifts.select ( |rfg| rfg.destination.name = 'NewDelhi, India' ).collect ( |rfg| rfg.gift )

But using query a or b would mean that the :has_many :through requirements that I have written will be of no use, since they are only double associative - The association assumes that only 2 models are involved in the association.

I am facing such models at a really high frequency, and a code fragment like query 1, I believe would really mprove understandability, of the code since the association table is never involved in the ruby code.

Can someone help me out with the model, or if it is even possible with the current associations that RoR supports?

Thanks, Abhin H

Hi,

   I have this requirement where in the association needs to be between 3 models.

I want a User to select a Gift to be sent to a particular Destinations. For this I created a Model RequestForGift

That name will be awkward, since the proper English plural would be "RequestsForGifts". Life will be easier if you change the model name to "GiftRequest" and name the table "gift_requests".

with foreign keys ( belongs_to ) to the User, Gift and Destination.Then I added the has_many relationships to each of the 3 Models to the other 2, but some how the usage of the association through the models is not comforting

class User < ActiveRecord::Base   has_many :RequestForGifts

Relationship names should be in lower case with underscores. If you change the model name to "GiftRequest", then you would have:    has_many :gift_requests    has_many :destinations, :through => :gift_requests, :uniq => true

There may be similar problems with your table definitions. I would write:   class GiftRequest < ActiveRecord::Base     :belongs_to :user     :belongs_to :gift     :belongs_to :destination     ...   end

and in the migration I would have:

   add_table :gift_requests do |t|       t.add_column :user_id, :integer, :null => false       t.add_column :gift_id, ...       t.add_column :destination_id, ...    end

If it's any consolation, the trend these days is to make association tables into their own models, so perhaps using GiftRequest isn't so "dirty," after all.

1) User.find(params[:id]).gifts.select( |g| { g.destination.name = 'New Delhi, India' } )

I don't think your desired interface would make logical sense in any framework, because a gift of a user has more than one destination. I'm not sure if there could be an interface that would start from User.gifts.

So I'd just bite the bullet, treat GiftRequest as a first-class object, and query it directly.

///ark