0

親モデルの対応する(子)モデルを簡単かつ効率的にフェッチして、テンプレートにレンダリングする方法はありますか?参加の有無にかかわらず、それを行う方法を知りたいです

たとえば、次の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でmerchant_id = 1を検索する場合)

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

このようにして、すべてのグループとそのサブモデルをループして、ERBを使用してフォームを生成できます。

ありがとうございました

4

2 に答える 2

2

コレクションを持つレコードのコレクションを反復処理すると、悪名高いN+1クエリが発生します。基本的に、すべてのProductGroupに対して、クエリを実行して、そのすべてのProductItemレコードをプルバックします。さらに、2つのレベルの関係で作業している場合はさらに悪化します。

これをより効率的に機能させるには、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が関連付けを設定するデフォルトの方法は、ハッシュのハッシュの代わりに実際のレコードを使用して、要求したデータ構造を満たす必要があります。ハッシュのハッシュを作成するには、とにかくロードする必要があります。

于 2013-02-20T16:32:08.137 に答える
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| ... }
于 2013-02-20T16:21:27.030 に答える