2009-06-03 52 views
1

我正在創建類別模型並使用awesome_nested_set插件(替換爲acts_as_nested_set)來處理層次結構。通過awesome_nested_set,創建對象,然後保存,然後放置在集合中。同樣,lft,rgtparent_id都是attr_protected,所以它們不能直接寫入。驗證嵌套集合中的節點移動

我遇到兩種情況將節點進入,我希望能夠趕上這樣我通知用戶(可能有更多的,我沒有考慮過的)設定時:

  1. 節點試圖放置爲自己的孩子(self.id == self.parent_id
  2. 節點嘗試自己的後代下被移動(self.descendants.include? self.parent_id == true

在這兩種情況下,此舉將失敗,但awesome_nested_set只會ra ise ActiveRecord::ActiveRecordError例外,其中的消息不像我希望能夠給用戶那樣描述。

awesome_nested_set具有許多移動節點的方法,其中所有呼叫move_to(target, position)(其中position:root:child,或:left:right一個target是所有position秒,但:root相關節點)。該方法觸發了一個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 

,在控制器中,我只需要說@category.save(parent_id),其中parent_idnil或家長的ID,和驗證,節點位置,並在模型中處理保存。