浏览 4491 次
锁定老帖子 主题:我对acts as tree的理解及应用
精华帖 (0) :: 良好帖 (0) :: 新手帖 (0) :: 隐藏帖 (0)
|
|
---|---|
作者 | 正文 |
发表时间:2007-04-30
前提: 手头上有《应用rails进行敏捷Web开发》一书 正文: 对书上已经提到就不重复了,在现实中树型结构的表是很多,我这里用家庭做一个例子。 表结构: ID Parent_id name People_count 0 null root 0 Mysql脚本 DROP TABLE IF EXISTS `databasename`.`people`; CREATE TABLE ` databasename `.`peoples` ( `id` int(11) NOT NULL auto_increment, `parent_id` int(11) default NULL, `name` varchar(100) NOT NULL default '', `people_count` int(11) NOT NULL default '0', PRIMARY KEY (`id`) ); class Person < ActiveRecord::Base acts_as_treerder => "name", :counter_cache => true def to_s puts "id is #{id},parent_id is #{parent_id},name is #{name},children_count is #{people_count}" end def self.display_children(parent) puts parent.children.map{|child| child.name}.join(",") end end 其中people_count是计数器,参看书:P244,用于记录节点孩子的个数. 在models类中要把:counter_cache => true 在rails.chm档中关于acts_as_tree的说明中,:counter_cahe默认值是false acts_as_tree(options = {}) Configuration options are: • foreign_key - specifies the column name to use for tracking of the tree (default: parent_id) • order - makes it possible to sort the children according to this SQL snippet. • counter_cache - keeps a count in a children_count column if set to true (default: false). # 树型结构 # root -------------根节点 # father ------一级子节点 # daughter --二级子节点 # son --二级子节点 # mother-------一级子节点 # 在test\unit\person_test.rb中写测试函数: def test_person Person.delete_all #清空表内容 root = Person.create(:name=>"root") puts root.to_s person = root.children.create(:name=>'father') puts person.to_s puts root.people_count #结果是0,与预期不符 puts root.children.size #结果是1,正确 person.children.create(:name=>'daughter') Person.display_children(person) person.children.create(:name=>'son') Person.display_children(person) #创建一个临时节点,用于查看删除 person.children.create(:name=>'temp') Person.display_children(person) temp = Person.find_by_name('father') puts "person people_count is : #{person.people_count}" #结果是0 puts "person people_count is : #{temp.people_count}" #结果是3 #注意我这里使用了两种不同的方式去得到孩子个数 printf "root children count is :", root.children_count() printf "\n" puts "person children size is :#{person.children.size}" #得到父亲 puts "person parent name is :#{person.parent.name}" end 通过查看表内容,记录与我们预期是一致的,当然你可以在测试时做一些错误的操作。看是否会报错。 在运行过程,注意到 puts root.people_count #结果是0,与预期不符 puts root.children.size #结果是1,正确 所以在运用时,这点要注意,事实上在数据库中people_count已经是1了, temp = Person.find_by_name('father') puts "person people_count is : #{person.people_count}" #结果是0 puts "person people_count is : #{temp.people_count}" #结果是3 对于这个问题,我查不到相关的资料,如果有谁知道,告诉我一下。 现在我都是使用size() 去得到记录总数 实例: 对于树我使用的是Livetree组件, 可以通过:http://www.epiphyte.ca/code/live_tree.html下载 同时,它提供了丰富的实例。 我在它的基础上做了些修改,实现了 添加同级节点,添加子节点,删除叶子节点 如果谁感觉兴趣可以发邮箱向我索要. seaofforest@126.com 我把几个主要代码贴出来: 放在<head>与</head>之间 <script type="text/javascript"> function OnClickItem(tree, itemId, itemIsLeaf, mapId) { alert("clicked on " + itemId); tree.activateItem(itemId); window.location.href="<%=url_for :controller => 'family',:action=>'show_tree' ,:id=>nil%>"+'/'+itemId } </script> 在body中添加用于显示树型结构: <div style="width:300px;height:415px"> <%= live_tree(:family_tree, { :initial_data_root => @root, n_click_item => "OnClickItem(this, item.id, item.isLeaf, item.isLeaf ? item.parent.id : item.id)" }) %> </div> 其它的添加,删除在测试代码中都有体现。如果想得到节点的层级,我现在还不知道rails有什么函数可以直接得到,但是可以通过在表中添加leve字段,用于保存节点的层级,这是我目前知道的比较简单的方法吧。 注: 阅读本文后,可以到 http://www.oracle.com/technology/global/cn/pub/articles/saternos-rails.html 查看《Rails 上的 HR 模式》一文 声明:ITeye文章版权属于作者,受法律保护。没有作者书面许可不得转载。
推荐链接
|
|
返回顶楼 | |
发表时间:2007-05-01
楼主把源代码部份排下版多好,整得都没心情看下去了。
《应用rails进行敏捷WEB开发》一书中对acts_as_tree的讲解有个小错误。 书中是这么说的: 引用 class Category < ActiveRecord::Base acts_as_tree : order => 'name' end 等价于 class Category < ActiveRecord::Base belongs_to :parent, :class_name => 'Category' has_many :children, :class_name => 'Category', :foreign_key => 'parent_id', : order => 'name', :dependent => true end 其实等价式belongs_to部份也必须声明 :foreign_key => 'parent_id' ,这点书中遗漏了。因为foreign_key如不特意设定,则按:class_name选项推导,从而出错了(成了'category_id'而非预期的'parent_id')。 附带说, :dependent => true 的表达方式过期了,选项不要再用true/false,而要从 :destroy,:delete_all,:nullify三者选其一,详情查看rails API doc。 |
|
返回顶楼 | |