如何在belongs_to中分配动态变量?

时间:2014-01-02 10:26:30

标签: ruby-on-rails activerecord

我有一些ActiveRecord模型设置如下:

订单型号:

class Order < ActiveRecord::Base
has_many :line_items, :dependent => :destroy  

订单项型号:

class LineItem < ActiveRecord::Base
belongs_to :order
belongs_to :product, :primary_key => "product_id"

产品型号:

class Product < ActiveRecord::Base

DB表看起来类似于这些(为简洁起见省略了列):

订单:

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

产品:

id | product_id | season
1  | 1000       | SS14    
2  | 1000       | AW14 
3  | 1001       | SS14 
4  | 1002       | SS14 
5  | 1003       | SS14 
6  | 1003       | AW14 

设置模型的方式意味着分配给订单项的产品是它找到的第一个产品,但是可以有多个具有相同ID的产品,由 season 分隔,这种情况不正确。

我需要做的是从订单表中的值指定产品分配的季节。例如。如果Order Season是AW14,分配给LineItem的产品也需要用于AW14。例如。如果LineItem的产品是1003而订单的季节是AW14,它应该选择ID为6而不是ID:5的行。

有没有办法指定哪些产品应该在模型中使用?

TIA。

编辑:

我应该补充一点,如果我在LineItem模型中对季节进行硬编码,我可以获得正确的产品,例如:

class LineItem < ActiveRecord::Base
belongs_to :order
belongs_to :product, -> { where season: "AW14" }, :primary_key => "product_id"

或者我可以在Product模型的default_scope中做类似的事情,但它需要来自Order而不是硬编码。

2 个答案:

答案 0 :(得分:2)

class LineItem < ActiveRecord::Base
  belongs_to :order
  belongs_to :product, :primary_key => 'product_id', :conditions => proc { "season = '#{order.name}'" }
end

对于LineItem.find(6).product,它将生成像这样的

的sql
SELECT "products".* FROM "products" WHERE "products"."product_id" = 1003 AND (season = 'AW14') LIMIT 1

答案 1 :(得分:0)

也许您可以在父模型(Order)上使用ActiveRecord Association Extension

#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

这样您就可以拨打@orders.products.season(AW2014),这将返回特定季节的产品

或者,您可以在Product模型中使用范围:

#app/models/product.rb
Class Product < ActiveRecord::Base
    scope :season, ->(season = nil) { where(season: season) }
end

#-> @order.products.season(AW2014)