Reputation: 18109
I'm wondering to what extent I can use associations in Rails. Take into consideration the following:
class User < ActiveRecord::Base
has_one :provider
has_many :businesses, :through => :provider
end
class Provider < ActiveRecord::Base
has_many :businesses
has_many :bids, :through => :businesses
belongs_to :user
end
class Business < ActiveRecord::Base
has_many :bids
belongs_to :provider
end
class Bid < ActiveRecord::Base
belongs_to :business
end
I am able to set up these nifty shortcuts like User.businesses
and Provider.bids
but what about doing something like User.bids
? Is it possible to associate an association, so to speak?
Upvotes: 13
Views: 10492
Reputation: 2963
If you just want to fetch the records, why not use use #delegate
? It works just fine, at least in the scenario you've described.
class User < ActiveRecord::Base
has_one :provider
delegate :bids, :to => :provider
end
class Provider < ActiveRecord::Base
has_many :businesses
has_many :bids, :through => :businesses
belongs_to :user
end
class Business < ActiveRecord::Base
has_many :bids
belongs_to :provider
end
class Bid < ActiveRecord::Base
belongs_to :business
end
Although in my not-so-humble-opinion you should just chain the methods because it's more straightforward, and you're no longer achieving the performance boost unless you go with some crazy custom SQL as tadman says.
Upvotes: 4
Reputation: 1957
There's nothing stopping you doing something like this afaik:
class User < ActiveRecord::Base
has_one :provider
has_many :businesses, :through => :provider
def bids
user_bids = []
businesses.each |business| do
user_bids += business.bids
end
user_bids
end
end
class Provider < ActiveRecord::Base
has_many :businesses
has_many :bids, :through => :businesses
belongs_to :user
end
class Business < ActiveRecord::Base
has_many :bids
belongs_to :provider
end
class Bid < ActiveRecord::Base
belongs_to :business
end
Then calling @user.bids should produce the desired result, you can also cache the bids and do other fancy stuff if you want.
Upvotes: -1
Reputation: 23450
This is entirely possible, but needs a little extra work. The following model definitions used in conjunction with the nested_has_many plugin you can fetch all bids belonging to a user with just @user.bids
class User < ActiveRecord::Base
has_one :provider
has_many :businesses, :through => :provider
has_many :bids, :through => :businesses
end
class Provider < ActiveRecord::Base
has_many :businesses
has_many :bids, :through => :businesses
belongs_to :user
end
class Business < ActiveRecord::Base
has_many :bids
belongs_to :provider
end
class Bid < ActiveRecord::Base
belongs_to :business
end
However getting a user from a bid will take a more work.
Upvotes: 6
Reputation: 211560
Although it is a very useful thing to have, you can't has_many :through a has_many :through relationship. This is a limitation of the join engine.
The alternatives are either to use a clever sub-select, or in this case a sub-sub select, or to deliberately denormalize the tables enough to reduce the join depth.
For example, since a Business is defined within the context of a Provider, it stands to reason that any Bid elements are also assigned, indirectly, to a Provider. Building a direct association between Bid and Provider would make querying bids directly easy.
Upvotes: 1