在Rails中使用has_one 、has_many 、belongs_to 和 has_and_belongs_to_may 来声明关系型数据库中的一对一,一对多和多对多的关系,但当想以树形的数据结构来表示分类的时候,这些基本的关联功能并不够,Rails在has_XXX关系的基础上,提供了acts as的扩展功能,如acts_as_list 、acts_as_tree 、 acts_as_nested_set。acts_as_tree就提供树状的结构来组织记录。(不知道为什么Rails2.0以后会取消掉,需要通过插件的方式来安装)
acts_as_nested_set的官方解释:
A Nested Set is similar to a tree from ActsAsTree. However the nested set allows building of the entire hierarchy at once instead
of querying each nodes children, and their children. When destroying an object,
a before_destroy trigger prunes the rest of the branch of object under the current object.
上面是引用自rubyonrails.org上的对于acts_as_nested_set的描述,并提供了一个简单的示例:
SQL脚本:
Sql代码 收藏代码
create table nested_objects (
id int(11) unsigned not null auto_increment,
parent_id int(11),
lft int(11),
rgt int(11),
name varchar(32),
primary key (id)
);
Ruby Model:
Ruby代码 收藏代码
class NestedObject < ActiveRecord::Base
acts_as_nested_set
end
acts_as_nested_set提供的方法:
root?() – 是否是根对象
child?() – 是否是子对象(拥有父对象)
unknown?() – 不知道该对象的状态(既不是根对象,也不是子对象)
add_child(child_object) – 为根对象添加一个子对象(如果child_object是一个根对象的话,则添加失败)
children_count() – 根对象的所有子对象的个数
full_set() – 重新找到所有对象
all_children() – 根对象的所有子对象
direct_children() –根对象的直接子对象
下面就使用acts_as_nested_set来生成一个Ext的Tree。
比如生成如下的树:
root
|_ Child 1
| |_ Child 1.1
| |_ Child 1.2
|_ Child 2
|_ Child 2.1
|_ Child 2.2
先来看一下对上面的树的一个图形化的解释:
这图还是比较清除的,请理解横线中的1到14这些数字,对应这个树,我们可能会有下面的数据:
这个也就是SQL脚本中的的lft和rgt的解释。
1.创建Rails工程:
rails ExtTree
2.安装act_as_nested_set:
ruby script/plugin install acts_as_nested_set
3.下载ext,解压下载后的压缩包并拷贝到ExtTree工程的public目录(public/ext)
4.创建模型对象:
ruby script/generate resource Category parent_id:integer lft:integer rgt:integer text:string
5.给模型对象Category加入acts_as_nested_set:
Ruby代码 收藏代码
class Category < ActiveRecord::Base
acts_as_nested_set
end
6.下面在CategoriesController中加入index方法,让它来转到index.html页面,并且为EXT TREE来生成JSON数据:
Ruby代码 收藏代码
class CategoriesController < ApplicationController
def index(id = params[:node])
respond_to do |format|
format.html # render static index.html.erb
format.json { render :json => Category.find_children(id) }
end
end
end
index方法有一个参数id,用来接收一个树的节点的id,我们就可以通过一个id来查找该节点的子节点。
7.实现CategoriesController中的find_children方法:
Ruby代码 收藏代码
#首先先得到树的根节点,再根据传过来的id找到根的子节点
def self.find_children(start_id = nil)
start_id.to_i == 0 ? root_nodes : find(start_id).direct_children
end
#如果parent_id为空,则为树的根节点
def self.root_nodes
find(:all, :conditions => 'parent_id IS NULL')
end
到这里,已经实现了基本的树形结构,但却还有一个问题,如果是树叶节点,既没有子节点的节点,图标应该显示为"-" ,不应该再能够伸展了,Ext Tree中提供的示例中给出的JSON数据中有一个leaf的属性,如果为true,则为树叶节点,如果为false,则为树枝节点,所以,我们还需要让我们生成的JSON数据用来leaf来标识树枝节点与树叶节点,在Category.rb中添加如下代码:
Ruby代码 收藏代码
def leaf
unknown? || children_count == 0
end
def to_json_with_leaf(options = {})
self.to_json_without_leaf(options.merge(:methods => :leaf))
end
alias_method_chain :to_json, :leaf
对于alias_method_chain,需要先说一下Ruby中的alias_method方法,在Ruby中有这样的用法:
Ruby代码 收藏代码
alias_method :old_method_name :new_method_name
它同alias很类似,但只能用法方法。
在Ruby中,可以使用方法链的手段来实现mix-in,如果想要用new_method来override old_method方法,就可以这样使用:
Ruby代码 收藏代码
alias_method :old_method_name :new_method_name
alias_method :new_method_name :old_method_name
而在Rails中,提供了一个更强大的方法:alias_method_chain。
下面是index.html.erb文件:
Html代码 收藏代码
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<meta http-equiv="content-type" content="text/html;charset=UTF-8"/>
<title>Rails Ext Tree</title>
<%= stylesheet_link_tag "../ext/resources/css/ext-all.css" %>
<%= javascript_include_tag :defaults %>
<%= javascript_include_tag "../ext/adapter/prototype/ext-prototype-adapter.js" %>
<%= javascript_include_tag "../ext/ext-all.js" %>
</head>
<body>
<div id="category-tree" style="padding:20px"></div>
<% javascript_tag do -%>
Ext.onReady(function(){
root = new Ext.tree.AsyncTreeNode({
text: 'Invisible Root',
id:'0'
});
new Ext.tree.TreePanel({
loader: new Ext.tree.TreeLoader({
url:'/categories',
requestMethod:'GET',
baseParams:{format:'json'}
}),
renderTo:'category-tree',
root: root,
rootVisible:false
});
root.expand();
});
<% end -%>
</body>
</html>
添加测试数据:
Ruby代码 收藏代码
root = Category.create(:text => 'Root')
root.add_child(c1 = Category.create(:text => 'Child 1'))
c1.add_child(Category.create(:text => 'Child 1.1'))
c1.add_child(Category.create(:text => 'Child 1.2'))
root.add_child(c2 = Category.create(:text => 'Child 2'))
c2.add_child(c21 = Category.create(:text => 'Child 2.1'))
c2.add_child(c21 = Category.create(:text => 'Child 2.2'))
最后的显示效果:
分享到:
相关推荐
这篇博客文章“Rails中应用Ext.tree:以中国的省市地区三级联动选择为例”提供了一个实用的示例,教我们如何利用Ext.js库中的Tree组件来实现这种功能。 首先,让我们了解Rails和Ext.js的基本概念。Rails是基于Ruby...
源码部分可能涵盖了如何在Rails项目中集成Ext JS库,以及如何利用Ext Scaffold插件生成定制的视图模板。工具部分可能涉及到其他辅助开发的工具或库,如自动完成、调试器或测试框架,以提升开发效率。 从压缩包中的...
**Ruby-GoOnRails:利用Rails生成器构建Golang应用** Ruby on Rails(简称Rails)是一种流行的Web开发框架,以其“约定优于配置”的理念和高效的开发速度受到开发者喜爱。而Go(Golang)则是一种静态类型、编译型的...
nifty-generators, 有用的Rails 生成器脚本集合 漂亮的生成器用于脚手架,布局文件,身份验证和更多的有用 Rails 生成器脚本的集合。设置 Rails 3将 gem 添加到你的。gem"nifty-generators", :group => :developm
- **丰富组件库**:Ext JS 提供了大量的用户界面组件,如 Data Grids、Tree Views、Tabs、Toolbars 和 Menus 等。 - **跨浏览器兼容性**:支持多种浏览器版本,如 Internet Explorer 6+、Firefox 1.5+、Safari 2+ 和...
`sitemap_generator` gem 是一个适用于Ruby on Rails框架的开源工具,它能够自动扫描你的Rails应用,生成包含所有路由的Sitemap。安装这个gem非常简单,只需要在Gemfile中添加以下行: ```ruby gem 'sitemap_...
简单的CLI利用Docker生成和运行Rails的环境
使用Rails生成Golang代码或管理Go应用开发go-on-rails是Rails生成器,旨在: 帮助开发和集成一些用Golang编写的API到现有的Rails应用程序,以实现高性能使用您熟悉的Rails工具开发和管理Golang应用程序项目将不太...
"Rails Erd"是一个Ruby gem,专门用于为Rails应用程序自动生成ERD,使得数据库设计和管理变得更加简单和直观。这个工具是由Voormedia开发的,版本号为0eb4577。 ERD是数据库设计的基础,它通过图形化方式展示了各个...
swagger-docs, 为 Rails api生成 swagger ui json文件,使用简单的DSL Swagger::Docs使用api为 Rails 应用生成swagger的ui json文件。 你可以向控制器类添加 swagger DSL,然后运行一个rake任务来生成json文件。 ...
字体配制文件 博文链接:https://babo.iteye.com/blog/72298
6. **Scaffolding**:Rails提供了快速生成基本CRUD(Create, Read, Update, Delete)操作的命令行工具,可以自动生成控制器、视图、样式表和测试文件,方便快速搭建原型。 7. **Testing**:Rails强调测试驱动开发,...
作者特别提到了“CRUD懶人大法Scaffold”,它是一种通过Rails自动生成代码的方式来快速搭建基本的CRUD操作,这大大简化了开发流程,使得开发者可以将更多的精力放在业务逻辑的实现上。 此外,书中还介绍了一些Rails...
总结来说,这个主题涵盖了Rails开发、RSpec测试、文档生成以及可能的文件转换技术。要深入学习这个话题,你需要熟悉Rails、RSpec的使用,理解CHM文件的结构,以及如何使用适当的工具和技术将代码行为测试和文档生成...
集合了Grape的所有Rails生成器脚本。 入门 将此行添加到 Rails 应用程序的 Gemfile 中: gem 'grape-api-generator' 然后运行bundle命令来安装它。 安装gem之后,您可以运行install生成器以生成基本的MyApp API...
rails_layout, 为各种前端框架生成 Rails 应用程序布局文件 RailsLayout gem使用这里 gem 可以设置你选择的前端框架的布局文件:Zurb基础 5.3Bootstrap 4.0Bootstrap 3.3它还将为 Bootstrap 或者基础设置设计视图。...