Reputation: 486
I have some ActiveRecord models set up like this:
Order Model:
class Order < ActiveRecord::Base
has_many :line_items, :dependent => :destroy
Line Item Model:
class LineItem < ActiveRecord::Base
belongs_to :order
belongs_to :product, :primary_key => "product_id"
Product Model:
class Product < ActiveRecord::Base
The DB tables look similar to these (columns omitted for brevity):
orders:
id | season
1 | SS14
2 | SS14
3 | AW14
line_items:
id | order_id | product_id
1 | 1 | 1000
2 | 1 | 1001
3 | 2 | 1000
4 | 3 | 1001
5 | 3 | 1002
6 | 3 | 1003
products:
id | product_id | season
1 | 1000 | SS14
2 | 1000 | AW14
3 | 1001 | SS14
4 | 1002 | SS14
5 | 1003 | SS14
6 | 1003 | AW14
The way the models are set up means that the product that is assigned to the line item is the first one it finds, but as there can be multiple products with the same ID, separated by season, it isn't correct for this scenario.
What I need to be able to do is to specify the season that the product is assigned to from the value in the order table. E.g. if the Order Season is AW14, the product assigned to the LineItem needs to be for AW14 too. E.g. if the LineItem's Product is 1003 and the Order's Season is AW14, it should pick up the row with ID: 6 and not ID: 5.
Is there a way to specify which Product should be used within the models?
TIA.
EDIT:
I should add that I can get the correct product to be assigned if I hard-code the season in the LineItem model, e.g.:
class LineItem < ActiveRecord::Base
belongs_to :order
belongs_to :product, -> { where season: "AW14" }, :primary_key => "product_id"
Or I can do a similar thing in the default_scope of the Product model, but it needs to come from the Order and not be hard-coded.
Upvotes: 0
Views: 736
Reputation: 76774
Maybe you could use ActiveRecord Association Extension on your parent model (Order
):
#app/models/order.rb
Class Order < ActiveRecord::Base
has_many :line_items, dependent: :destroy
has_many :products, through: :line_items do
def season(var)
where(season: var)
end
end
end
This will allow you to call @orders.products.season(AW2014)
, which will return the products for that specific season
Alternatively, you could use a scope in the Product
model:
#app/models/product.rb
Class Product < ActiveRecord::Base
scope :season, ->(season = nil) { where(season: season) }
end
#-> @order.products.season(AW2014)
Upvotes: 0
Reputation: 1692
class LineItem < ActiveRecord::Base
belongs_to :order
belongs_to :product, :primary_key => 'product_id', :conditions => proc { "season = '#{order.name}'" }
end
for LineItem.find(6).product it will generate the sql like this
SELECT "products".* FROM "products" WHERE "products"."product_id" = 1003 AND (season = 'AW14') LIMIT 1
Upvotes: 2