SteveA
SteveA

Reputation: 486

How can I assign a dynamic variable in a belongs_to?

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

Answers (2)

Richard Peck
Richard Peck

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

nickcen
nickcen

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

Related Questions