我使用has_many :through
关系创建了一个自引用数据库:
**Product**
name
**Ingredient**
quantity
product_id
product_component_id
我可以有一个鸡蛋,一盒12个鸡蛋,还有一套16个纸箱。
我试图写一个循环,从一个产品开始,将每个产品的所有组件分解到最基本的状态。目标是退回任何给定产品中的所有基本产品,这样纸箱将退回12个鸡蛋,而平板电脑将退回192个鸡蛋。
我试了一下,这就是我的进展:
def product_breakdown
results = []
ingredients.each do |ingredient|
if ingredient.product_component_id == nil
results += ingredient
else
Keep digging deeper?
end
end
return results
end
当谈到使用循环时,我遗漏了一个完整的概念。如果有人能就这需要的概念的名称提出建议,我将不胜感激。
为了更清楚地编辑我复制的数据库的关系。
class Product < ActiveRecord::Base
has_many :ingredients
has_many :product_components, :through => :ingredients
end
class Ingredient < ActiveRecord::Base
belongs_to :product
belongs_to :product_component, class_name: "Product", :foreign_key => "product_component_id"
end
我建议使用each_with_object
来构建数组。这样,您甚至不需要results
变量,只需返回each_with_object的返回值即可。
如何区分单元、纸箱和平板?
如果我理解正确,每个成分都有一个component
,可以是nil
、Carton
或Flat
?一个纸箱总是包含12个单元,而一个扁平的16个纸箱?还有一个source
,它是一种成分(鸡蛋、牛奶等)
在这种情况下,我将在Ingredient
上定义两个助手方法,一个as_unit
类方法和一个unit_quantity
实例方法:
def unit_quantity
case product_component_id
when nil
quantity
when CARTON_COMPONENT_ID
12 * quantity
when FLAT_COMPONENT_ID
192 * quantity
end
end
def self.as_unit ingredients
source_ids = ingredients.map(&:product_source_id).uniq
raise "Can't join different types together" if source_ids.count != 1
source_id = source_ids.first
quantity = ingredients.reduce(0) { |total, ingredient| total += ingredient.unit_quantity }
Ingredient.new quantity: quantity, product_component_id: nil, product_source_id: source_id
end
这样,您可以将products_breakdown
重写为:
def products_breakdown ingredients
ingredients.group_by(&:product_source_id).map do |_, ingredients|
Ingredient.as_unit ingredients
end
end
这将导致:
$ ingredients
#=> [<Ingredient: 3 Cartons of Egg>, <Ingredient: 2 Flats of Milk>, <17 Units of Egg>]
$ product_breakdown ingredients
#=> [<Ingredient: 53 Units of Egg>, <Ingredient: 384 Units of Milk>]
这就是你想要的吗?我不确定我是否完全理解你的问题。。。