2009-06-03 16 views
1

私はカテゴリモデルを作成し、awesome_nested_setプラグイン(acts_as_nested_setの代わり)を使用して階層を処理しています。 awesome_nested_setを使用すると、オブジェクトが作成され、保存され、セット内に配置されます。同様に、lft,rgtおよびparent_idattr_protectedであるため、直接書き込むことはできません。ネストされたセット内のノード移動の妥当性確認

私はので、私は、ユーザーが(私はまだ考えていないこと以上があるかもしれない)に通知することをキャッチすることができるようにしたいセットにノードを配置するとき、私は二つの状況に実行しています:

  1. ノードが自身の子として配置しようとするノードは、自身の子孫の下に移動しようとする(self.id == self.parent_id
  2. self.descendants.include? self.parent_id == true

は、両方の場合において、移動は失敗するが、awesome_nested_setう意志だけですiseはActiveRecord::ActiveRecordError例外ですが、私はユーザーに与えることができるようにわかりやすいメッセージではありません。

awesome_nested_setは(position:root:child:left又は:righttargetの一つである、すべてのposition Sしかし:rootための関連するノードである)すべてのコールmove_to(target, position)ノード移動の多数の方法を有しています。このメソッドはbefore_moveコールバックを起動しますが、発生前に移動を検証する方法は提供していません。移動を検証するために、コールバックが受け取らないターゲットと位置にアクセスする必要があります。

は、誰もが(別の方法でのbefore_moveコールバックに目標と位置を渡す方法を持っていることによってのいずれか)awesome_nested_setでの動きを検証する方法、または私が検証できるようになる他のネストされたセットのプラグインのいずれかを知っていますか?私は自分のプラグインをフォークしたり書くことを好まない。

答えて

2

ここで私が思いついたのソリューションです:

class Category < ActiveRecord::Base 
    acts_as_nested_set :dependent => :destroy 

    #=== Nested set methods === 

    def save_with_place_in_set(parent_id = nil) 
    Category.transaction do 
     return false if !save_without_place_in_set 
     raise ActiveRecord::Rollback if !validate_move parent_id 

     place_in_nested_set parent_id 
     return true 
    end 

    return false 
    end 

    alias_method_chain :save, :place_in_set 

    def validate_move(parent_id) 
    raise ActiveRecord::RecordNotSaved, "record must be saved before moved into the nested set" if new_record? 
    return true if parent_id.nil? 

    parent_id = parent_id.to_i 

    if self.id == parent_id 
     @error = :cannot_be_child_of_self 
    elsif !Category.all.map(&:id).include?(parent_id) 
     @error = :given_parent_is_invalid 
    elsif descendants.map(&:id).include? parent_id 
     @error = :cannot_be_child_of_descendant 
    end 

    errors.add(:parent_id, @error) if @error 
    return @error.nil? 
    end 

    def place_in_nested_set(parent_id) 
    if parent_id.nil? || parent_id.blank? 
     move_to_root 
    else 
     move_to_child_of parent_id 
    end 
    return true 
    end 
end 

さて、コントローラでは、私はちょうどparent_idnilまたは親のID、および検証、ノード配置である@category.save(parent_id)を、言う必要があるが、 、保存はモデルで処理されます。