views:

38

answers:

2

How would you map the dashed association using ActiveRecord? Is there any ActiveRecord-way of doing it? What I want is to get all unique available promotions for a particular item.

Diagram

Here are things I thought but I don't really like:

Using custom finder

class Item < ActiveRecord::Base
  has_many :promotions, :finder_sql => "SELECT..FROM promotions..purchase_option_id IN (...)"
end

The dirty and inefficient but rubyish way

my_item.purchase_options.map(&:promotion).uniq

Breaking the PurchaseOption<->Promotion HABTM association and creating a new one for Item<->PromotedPurchaseOption

class Item < ActiveRecord::Base
  has_many :promoted_purchase_options
  has_many :promotions, :through => :promoted_purchase_options
end

Other thoughts

I don't think it's a good idea to use named scopes or defining new methods This won't simply work or will execute inefficient queries if using them:

Item.first.promotions.count
Item.first.promotions.available
Promotion.first.items.all
A: 

I don't know why you're opposed to named scopes or custom methods. These things can help reduce complexity by encapsulating a lot of the query logic. Whenever possible avoid custom finder_sql on your relationships.

If you're using a deprecated has_and_belongs_to_many relationship method, you should probably switch it to a straight join model. The has_many ..., :through approach will give you a lot more control over the links between models, and you can alter the properties of the join model directly.

tadman
I don't want named_scopes/methods because I will be chaining the association and AR won't be able to generate the proper SQL.what do you mean by deprecated? the problem is that I don't need the "straight model", it just add complexity.
knoopx
The `has_and_belongs_to_many` association is not deprecated.
John Topley
Technically it is still supported, but lacks many of the features that a has_many ... :through relationship offers, such as being able to easily update attributes on the join. Prior to there being support for :through (Rails 1.2?) these were the only way to go. I should have said "fallen out of favor" rather than strictly deprecated.
tadman
ActiveRecord is usually pretty good about figuring out what you mean when you chain associations, so it's a better way to go than rolling your own SQL unless strictly required.
tadman
+1  A: 

Maybe this one:

class Item < ActiveRecord::Base
  has_many :purchase_options
  has_many :promotions, :through => :purchase_options, :uniq => true
end
fantactuka
it would work if `PurchaseOption`<->`Promotion` association was of type `has_one`, `has_many` or `belongs_to` but not for `has_and_belongs_to`, please review the ER diagram
knoopx
This is the better way to organize it. I'm with @fantactuka on this one.
tadman