Rails:如何获取,然后迭代父模型的所有子(+ child等)模型?

时间:2013-02-20 15:56:25

标签: ruby-on-rails ruby rails-activerecord

有没有办法轻松有效地获取父模型的相应(子)模型,然后在模板中呈现它?我想知道如何使用和不使用连接

例如,请考虑以下3个表:

# ProductGroup is the highest parent
class ProductGroup < ActiveRecord::Base
  attr_accessible :name, :merchant_id
  has_many :product_items
  has_many :product_group_selections
end

# ProductItem is a child of ProductGroup
class ProductItem < ActiveRecord::Base
  attr_accessible :base_price, :name, :product_group_id
  belongs_to :product_group
end

# ProductGroupSelection is a child of ProductGroup
class ProductGroupSelection < ActiveRecord::Base
  attr_accessible :name, :price_extra, :product_attr_group_id, :product_item_id
  belongs_to :product_group
  has_many :product_group_selection_attrs
end

# ProductGroupSelectionAttr is a child of ProductGroupSelection
class ProductGroupSelectionAttr < ActiveRecord::Base
  attr_accessible :name, :product_group_id
  belongs_to :product_group_selection
end

我想要的是一个看起来像这样的数据结构(当搜索product_groups for merchant_id = 1时)

merchant_id 1 => {  
          ProductGroup.name, ProductGroup.merchant_id,  
          ProductItems => [...],
          ProductGroupSelections => {ProductGroupSelections.name, ProductGroupSelectionAttrs => [...]}
}

通过这种方式,我可以循环遍历所有组及其子模型,以使用ERB生成表单。

谢谢

2 个答案:

答案 0 :(得分:2)

当迭代一组记录时,这些记录又会产生集合,你将遇到臭名昭着的N + 1查询。基本上对于每个ProductGroup,您将运行查询以撤回其所有ProductItem记录。如果你处理两级关系,那就更糟了。

为了更有效地完成这项工作,您希望利用ActiveRecord定义的包含作为在尽可能少的查询中急切加载关联的方法。

ProductGroup.includes(:product_items).includes(:product_group_selections => :product_group_selection_attrs)

从那里你只需添加你需要的任何条件,为ProductGroup加载的任何条件都将确保所有相关模型也被加载。

现在,您只需正常迭代您的关联。假设@product_groups有一个ProductGroup

的集合
@product_groups.each do |product_group|
  # do stuff with product_group
  product_group.product_items.each do |product_item|
    # do stuff with product_item
  end
  product_group.product_group_selections do |product_group_selection|
    # do stuff with product_group_selection
    product_group_selection.product_group_selection_attrs do |product_group_selection_attr|
      # do stuff with product_group_selection_attr
    end
  end
end

rails设置关联的默认方式应该满足您要求的数据结构,只需要实际记录而不是散列哈希值,无论如何都需要加载以创建哈希哈希值。

答案 1 :(得分:0)

也许是这样的:

class ProductGroup < ActiveRecord::Base

    # I have no idea what to call this method
    def merchant_data    
        {:name => self.name, :merchant_id => self.merchant_id, :items => self.product_items, :selections => self.product_group_selections}
    end

end

你的控制器里面你会有这样的东西:

def merchant_search    
  @product_group = ProductGroup.find_by_merchant_id(params[:merchant_id})
  @merchant_data = @product_group.merchant_data    
  #@merchant_data => {:name=>"...", :merchant_id=> 1, :items=>[....], :selections=>[..]}
end

只需在视图中使用哈希,类似于如何使用任何其他实例变量,只有这次使用哈希。例如,如果您想循环遍历返回的数据结构中的所有项目:

@merchant_data[:items].each {|item| ... }