2

カテゴリモデルを作成し、awesome_nested_setプラグイン(の代わりacts_as_nested_set)を使用して階層を処理しています。を使用awesome_nested_setすると、オブジェクトが作成され、保存されてから、セット内に配置されます。同様に、、lftおよびrgtparent_id直接attr_protected書き込むことができないためです。

ノードをキャッチできるようにしたいセットに配置して、ユーザーに通知するときに、2つの状況が発生しています(まだ考えていないことがあるかもしれません)。

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

どちらの場合も、移動は失敗しますがawesome_nested_set、例外が発生するだけでActiveRecord::ActiveRecordError、ユーザーに提供したいほど説明的ではないメッセージが表示されます。

awesome_nested_setには、すべてが呼び出すノード移動メソッドがいくつかありますmove_to(target, position)(ここで、はposition、、、またはのいずれかであり、はすべてのsに関連するノードです)。このメソッドはコールバックを起動しますが、移動が発生する前に検証する方法を提供していません。移動を検証するには、コールバックが受信しないターゲットと位置にアクセスする必要があります。:root:child:left:righttargetposition:rootbefore_move

入居を検証する方法awesome_nested_set(別のメソッドによってターゲットと位置をbefore_moveコールバックに渡す方法がある)、または検証できる別のネストされたセットプラグインのいずれかを知っている人はいますか?自分のプラグインをフォークしたり書いたりしたくない。

4

1 に答える 1

3

これが私が思いついた解決策です:

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

さて、コントローラーでは、親の ID または@category.save(parent_id)場所を指定するだけでよく、検証、ノードの配置、および保存はモデルで処理されます。parent_idnil

于 2009-06-29T19:00:50.863 に答える