论坛首页 编程语言技术论坛

我对acts as tree的理解及应用

浏览 4491 次
精华帖 (0) :: 良好帖 (0) :: 新手帖 (0) :: 隐藏帖 (0)
作者 正文
   发表时间:2007-04-30  
最近在看敏捷一书,把我对Acts as tree一节的理解写下。
前提:
手头上有《应用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 模式》一文
   发表时间: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。



0 请登录后投票
论坛首页 编程语言技术版

跳转论坛:
Global site tag (gtag.js) - Google Analytics