【问题标题】:Validating a node move in a nested set验证嵌套集中的节点移动
【发布时间】:2009-06-03 20:45:19
【问题描述】:

我正在创建一个类别模型并使用awesome_nested_set 插件(acts_as_nested_set 的替代品)来处理层次结构。使用awesome_nested_set,对象被创建,然后保存,然后放置在集合中。同样,lftrgtparent_idattr_protected,因此无法直接写入。

在将节点放入我希望能够捕获的集合中时,我遇到了两种情况,以便我通知用户(可能还有更多我还没有想到的):

  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:root:child:left:right 之一,而target 是相关的所有positions 但:root 的节点)。该方法触发before_move 回调,但没有提供一种我可以看到的在移动发生之前验证移动的方法。为了验证移动,我需要访问回调未接收到的目标和位置。

有谁知道在awesome_nested_set 中验证移动的方法(通过另一种方法将目标和位置传递给before_move 回调的方法),或者另一个可以让我使用的嵌套集插件证实?我不想派生或编写自己的插件。

【问题讨论】:

    标签: ruby-on-rails validation plugins nested-sets


    【解决方案1】:

    这是我想出的解决方案:

    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
    

    现在,在控制器中,我只需要说@category.save(parent_id),其中parent_idnil 或父ID,验证、节点放置和保存在模型中处理。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2013-10-29
      • 2013-10-07
      • 2021-09-05
      • 2019-12-31
      • 1970-01-01
      • 2010-12-08
      • 2016-03-15
      相关资源
      最近更新 更多