Techioz Blog

Nested Set Gem はどのように機能するのでしょうか?また、それをプロジェクトに組み込むにはどうすればよいですか?

概要

最近、現在の Rails アプリ関係では gem ネストされたセットを使用する必要があるとアドバイスを受けました。 ( 前回のスレッド / 質問はこちら) 私は現在 3 つのモデルを持っています。

カテゴリにはサブカテゴリが_多くあります サブカテゴリはカテゴリに属し、製品が_多くあります。 製品はサブカテゴリに属します。こんな感じで表示したかったのですが +カテゴリー —-サブカテゴリ - - - - 製品 - - - - 製品 —-サブカテゴリ - - - - 製品 - - - - 製品

+カテゴリー —-サブカテゴリ - - - - 製品 - - - - 製品

それでは、これをnested_setで行う場合、モデルでどのように設定すればよいでしょうか?サブカテゴリと製品モデルを削除して、カテゴリ モデルに act_as_nested_set を追加するだけでよいでしょうか?モデルの処理が完了したら、作成したネストされたセット内にノードを作成できるようにするには、コントローラーのアクションを何を更新すればよいでしょうか?

このnested_setリストのCRUD、作成、読み取り、更新、および破棄を行う方法を理解するのに役立つと思います。

これは私がすでに持っているコードです

カテゴリコントローラー:

class CategoriesController < ApplicationController
def new
  @category = Category.new
  @count = Category.count
end

def create
@category = Category.new(params[:category])
if @category.save
  redirect_to products_path, :notice => "Category created! Woo Hoo!"
else
  render "new"
end
end

def edit
  @category = Category.find(params[:id]) 
end

def destroy
  @category = Category.find(params[:id])
  @category.destroy
  flash[:notice] = "Category has been obliterated!"
  redirect_to products_path
end

def update
  @category = Category.find(params[:id])

if @category.update_attributes(params[:category])
  flash[:notice] = "Changed it for ya!"
  redirect_to products_path
else 
  flash[:alert] = "Category has not been updated."
  render :action => "edit"
end
end

def show
  @category = Category.find(params[:id])
end

def index
  @categories = Category.all
end 
end

カテゴリモデル:

class Category < ActiveRecord::Base
  acts_as_nested_set
  has_many :subcategories
  validates_uniqueness_of :position
  scope :position, order("position asc")

end

サブカテゴリモデル:

class Subcategory < ActiveRecord::Base
  belongs_to :category
  has_many :products
  scope :position, order("position asc")
end

そして最後に、製品モデル:

class Product < ActiveRecord::Base
  belongs_to :subcategory
  has_many :products
  scope :position, order("position asc")
end

助けていただければ幸いです。

解決策

カテゴリと製品は次のようにします。

class Product > ActiveRecord::Base
  belongs_to :category
end

class Category > ActiveRecord::Base
  has_many :products
  acts_as_nested_set
end

class CategoryController < ApplicationController
   def create

      @category = params[:id] ? Category.find(params[:id]).children.new(params[:category]) : Category.new(params[:category])

      if @category.save
          redirect_to products_path, :notice => "Category created! Woo Hoo!"
      else
          render "new" 
      end
   end

   def new
      @category = params[:id] ? Category.find(params[:id]).children.new : Category.new
   end

   def index
      @categories = params[:id] ? Category.find(params[:id]).children : Category.all
   end
end

#config/routes.rb your categories resource could be something like..
resources :categories do
   resources :children, :controller => :categories, 
                              :only => [:index, :new, :create]
end

この方法は、製品をあらゆるレベルのカテゴリに入れることができるため、最も柔軟です。