Slick23
Slick23

Reputation: 5897

nested has_many :through in rails 3

I know Rails doesn't support nested has_many :through relationships, though there's been talk and an open ticket about a patch since as early as Rails 2.

I did come across a plugin that's pretty slick, but the master branches don't work with Rails 3 and I'm hesitant to use it for mission critical tasks in the app hence the lack of active recent development. So -- what's the best way to deal with these relations.

class Author < ActiveRecord::Base
  has_many :contracts
  has_many :products, :through => :contracts

class Product < ActiveRecord::Base
  has_many :contracts
  has_many :orders
  has_many :authors, :through => :contracts

class Contracts < ActiveRecord::Base
  belongs_to :author
  belongs_to :product

So, all the being what it is it would be great to be able to get at orders this by adding this to the Author model:

has_many :orders, :through => :products

But alas, you cannot -- at least without the plugin. So, my question is what's the best approach to accessing all of an author's orders when the only association is between the join model, Contracts?

Upvotes: 4

Views: 3263

Answers (3)

Wolfram Arnold
Wolfram Arnold

Reputation: 7273

If you're not trying to create objects through the nested association, and you want to use it for lookup only, then scopes in Rails 3 are a great way to do this. Alternatively you could implement a class method.

I've had this kind of thing as an example in a class I taught recently, the Rails 3 version of the code is here: https://github.com/wolframarnold/Efficient-TDD-Rails3/blob/master/app/models/user.rb

See the definition of the items method. The specs are here: https://github.com/wolframarnold/Efficient-TDD-Rails3/blob/master/spec/models/user_orders_spec.rb

Rails 3.1 update: As one commenter already noted, Rails 3.1 does support has_many :through associations more than one level deep.

Upvotes: 8

Kyle
Kyle

Reputation: 121

The ticket doesn't seem to be active any more for including the patch in Rails core. I'd submit it ... seems like it should be something that should just work in Rails.

Upvotes: 1

Shreyas
Shreyas

Reputation: 8757

As I see it you have 2 options:

  1. You may need to re-consider your modelling decisions. For example, establish a many-to-many association between a Customer and a Product through an Order. And then incubate the Contract.

  2. Use a named scope (or scope in Rails 3) to fetch the author's orders.

If pressed, I would go with option 1.

Upvotes: 1

Related Questions