`
taito
  • 浏览: 94494 次
  • 性别: Icon_minigender_1
  • 来自: 上海
社区版块
存档分类
最新评论

acts_as_nested_set的增强版BetterNestedSet

阅读更多
BetterNestedSet 插件是nested_set的增加版。不仅多了一些方法,而且结构更加精简,查询更方便。

==安装

script/plugin install svn://rubyforge.org/var/svn/betternestedset/trunk


==数据结构

例子:
root
    |_ Child 1
      |_ Child 1.1
      |_ Child 1.2
    |_ Child 2
      |_ Child 2.1
      |_ Child 2.2

形象的表示如下图所示:
    ___________________________________________________________________
   |  Root                                                             |
   |    ____________________________    ____________________________   |
   |   |  Child 1                  |   |  Child 2                  |   |
   |   |   __________   _________  |   |   __________   _________  |   |
   |   |  |  C 1.1  |  |  C 1.2 |  |   |  |  C 2.1  |  |  C 2.2 |  |   |
   1   2  3_________4  5________6  7   8  9_________10 11_______12 13  14
   |   |___________________________|   |___________________________|   |
   |___________________________________________________________________|

数据表:

  id | parent_id | lft  | rgt  | data
    1 |           |    1 |   14 | root
    2 |         1 |    2 |    7 | Child 1
    3 |         2 |    3 |    4 | Child 1.1
    4 |         2 |    5 |    6 | Child 1.2
    5 |         1 |    8 |   13 | Child 2
    6 |         5 |    9 |   10 | Child 2.1
    7 |         5 |   11 |   12 | Child 2.2

必要的字段:parent_id,lft,rgt
数据迁移脚本如下:
# TAITO BetterNestedSet Mig
class CreateCategories < ActiveRecord::Migration
  def self.up
    create_table :categories do |t|
      t.column :name, :string, :null=>false
      t.column :parent_id, :integer
      t.column :lft,       :integer
      t.column :rgt,       :integer
    end
  end

  def self.down
    drop_table :categories
  end
end


=Model中
class Category < ActiveRecord::Base
  acts_as_nested_set
end


数据的建立和acts_as_nested_set差不多。唯一的区别是添加子级的方法不一样:

如:
root = Category.create(:name => "root")
child = Category.create(:name => "child")

child.move_to_child_of root  # 移动过去



==更多实用方法

root - root item of the tree (the one that has a nil parent; should have left_column = 1 too)
roots - root items, in case of multiple roots (the ones that have a nil parent)
level - number indicating the level, a root being level 0
ancestors - array of all parents, with root as first item
self_and_ancestors - array of all parents and self
siblings - array of all siblings, that are the items sharing the same parent and level
self_and_siblings - array of itself and all siblings
children_count - count of all immediate children
children - array of all immediate childrens
all_children - array of all children and nested children
full_set - array of itself and all children and nested children

==原创的辅助方法
module NestedSetList  
  def first?    
      parent.nil? or parent.lft==self.lft-1 
  end
  def last?
    parent.nil? or parent.rgt==self.rgt+1
  end
  def higher_item
    list = self_and_siblings
    i = list.index(self)
    i==0 ? self : list[ i-1 ]
  end
  def lower_item
    list = self_and_siblings
    i = list.index(self)
    i==list.size-1 ? self : list[ i+1 ]
  end
  def move_higher
    move_to_left_of( higher_item ) if higher_item
  end
  def move_lower
    move_to_right_of( lower_item ) if lower_item
  end
  def move_to_top
    move_to_left_of( self_and_siblings.first )
  end
  def move_to_bottom
    move_to_right_of( self_and_siblings.last )  
  end
end


在model中调用:
  include NestedSetList

==注意

Rails 2.1版本下使用,会有错误,这是因为2.1对于 attributes_with_quotes ,发生了很大变化。

BetterNestedSet Rails2.1 ArgumentError

请修改插件lib/better_nested_set.rb 文件的这一段
......
def attributes_with_quotes(include_primary_key = true, include_readonly_attributes = true, attribute_names = @attributes.keys)
  left_and_right_column = [acts_as_nested_set_options[:left_column], acts_as_nested_set_options[:right_column]]
  quoted = {}
  connection = self.class.connection
  attribute_names.each do |name|
    if column = column_for_attribute(name)
      quoted[name] = connection.quote(read_attribute(name), column) unless !include_primary_key && (column.primary || left_and_right_column.include?(column.name))
    end
  end
  include_readonly_attributes ? quoted : remove_readonly_attributes(quoted)
end
......

==其它

acts as section map 是一个针对acts树结构的一个扩展插件。可以生成表格形式的结构图.

=安装方法
./script/plugin install http://xibbar.net/svn/rails/plugins/trunk/acts_as_section_map/
4
0
分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics