锁定老帖子 主题:美就是生产力(Rails美学宣言阐释)
该帖已经被评为精华帖
|
|
---|---|
作者 | 正文 |
发表时间:2006-04-26
hehe,甭管怎样,喜欢看。快继续吧
|
|
返回顶楼 | |
发表时间:2006-04-26
自Rails1.1 :through出现后has_and_belongs_to_many基本处于半作废状态, 只有少数情况才会用到(比如自引用多对多).
|
|
返回顶楼 | |
发表时间:2006-04-26
robbin 写道 potian 写道 robbin 写道 potian 写道 我的建议是你看RubyForRails
我也这样觉得,要是先看programming ruby,学习速度太慢了,谢谢指点。 不客气 我指的是一本另外的书 已经用骡子拽下来了,粗粗一看,似乎是专为没有ruby背景的rails程序员写的,挺合适,就是可读性没有agile 那本书那么好。 RubyForRails 是哪本书? |
|
返回顶楼 | |
发表时间:2006-04-26
既然cookoo提到了,我们顺便看看自引用,所谓自引用,就是一个表中的对象相互引用,看看典型的组织机构,首先是简单的多对多
为了实现这个结构,我们定义如下模型 class Organization < ActiveRecord::Base has_and_belongs_to_many :children, :class_name => 'Organization', :join_table => 'org_relationships', :foreign_key => 'parent_id', :association_foreign_key => 'child_id' has_and_belongs_to_many :parents, :class_name => 'Organization', :join_table => 'org_relationships', :foreign_key => 'child_id', :association_foreign_key => 'parent_id' end 这下读不了了 (: , class_name是指对方属于什么类,我们知道不管Parent还是child都是Organization,连接表当然也是在同一个表中org_relationships,这个表有两个字段,parent_id, child_id. 从parent的角度来看,他是通过parent_id来选取的,譬如where parent_id = 自己的id,和他相关的children是通过child_id来得到的 SELECT * FROM organizations INNER JOIN orgrelationships ON organizations.id = orgrelationships.child_id WHERE (orgrelationships.parent_id = 自己的id ) ok,我们来建立上边这种组织机构 china = Organization.create(:name => "china") jiangsu = Organization.create(:name => "jiangsu") zhejiang = Organization.create(:name => "zhejiang") account = Organization.create(:name => "accout") china.children << [jiangsu, zhejiang, account] shaoxin = Organization.create(:name => "shaoxin") hangzhou = Organization.create(:name => "hangzhou") zhejiang_account = Organization.create(:name => "zhejiang account") zhejiang.children <<[shaoxin, hangzhou, zhejiang_account] account.children << [zhejiang_account] hangzhou_account = Organization.create(:name => "hangzhou_account") hangzhou_account.parents << [hangzhou , zhejiang_account] 我们来看看是不是正确: def show_relationship(org) puts "parents:" unless org.parents.empty? puts org.parents.map {|parent| parent.name}.join "," end puts "children:" unless org.children.empty? puts org.children.map {|child| child.name}.join "," end end 当然代码可以写得更简单,但是给大家看得明白点 show_relationship(china) parents: children: jiangsu,zhejiang,accout show_relationship(zhejiang) parents: china children: shaoxin,hangzhou,zhejiang account show_relationship(zhejiang_account) parents: zhejiang,account children: hangzhou account 复杂吧,其实还好,就是两个关系声明,你知道我们前面的所有事情照样可以做: Organization.find_by_name("china").children.find_by_name("zhejiang") 等等等等 当然,这还是太简单了,让我们来看看accountability的实现 |
|
返回顶楼 | |
发表时间:2006-04-27
这个组织机构实在够混乱了,我们整理整理
好复杂呦,真的吗?真的很复杂吗?(想起了以前Javaeye一个著名的帖子) 在看下面的代码之前,先想一下该如何实现,当然,我也想了好久(有2-3分钟之久),不过这个图花的时间可长了,不知道能不能在Java雇一个专业画图手,可惜不能在这里放白班 OK,废话少说 class Accountability < ActiveRecord::Base belongs_to :parent, :foreign_key => "parent_id", :class_name => "Organization" belongs_to :child, :foreign_key => "child_id", :class_name => "Organization" end class Organization < ActiveRecord::Base has_many :accountabilities_as_parent, :foreign_key => 'parent_id', :class_name => 'Accountability' has_many :accountabilities_as_child, :foreign_key => 'child_id', :class_name => 'Accountability' has_many :parents, :through => :accountabilities_as_child has_many :children, :through => :accountabilities_as_parent end 不要被吓到,只要每个人跟我念一遍,Rational公司就会倒闭 CREATE TABLE `accountabilities` ( `id` int(11) NOT NULL auto_increment, `parent_id` int(11) default NULL, `child_id` int(11) default NULL, `acctype` varchar(20) default NULL, PRIMARY KEY (`id`) ) 首先我得承认自己偷懒了,acctype直接变成一个string Accountability这个类我懒得念了。看看Organization, 1 class Organization < ActiveRecord::Base 2 has_many :accountabilities_as_parent, :foreign_key => 'parent_id', :class_name => 'Accountability' 3 has_many :accountabilities_as_child, :foreign_key => 'child_id', :class_name => 'Accountability' 4 has_many :parents, :through => :accountabilities_as_child has_many :children, :through => :accountabilities_as_parent 5 end 有一点小小的弯头,由于我们是自引用的,所以4,5两句话has_many :through没地方好through,但是我们可以通过has_many模拟出来,说到底,through就是为了能够建立连接关系,当我们需要连接的时候,需要一个外键引用而已,如果我要得到某个人的子,那么就需要parent_id = 自己的id,所以4行,through accountabilities_as_parent,而accountabilities_as_parent则使用外键parent_id SELECT organizations.* FROM organizations INNER JOIN accountabilities ON organizations.id = accountabilities.child_id WHERE (accountabilities.parent_id = 自己的id ) 好了好了,咱们来实证 china = Organization.create(:name => "china") jiangsu = Organization.create(:name => "jiangsu") zhejiang = Organization.create(:name => "zhejiang") account = Organization.create(:name => "account") zhejiang_account = Organization.create(:name => "zhejiang account") 不过这一次,可不能乱来了 china和zhejiang,jiangsu,都是regional的关系 Accountability.create(:parent=>china, :child=>jiangsu, :acctype =>"regional") Accountability.create(:parent=>china, :child=>zhejiang, :acctype =>"regional") 但是china和account是organizational关系 Accountability.create(:parent=>china, :child=>account, :acctype =>"organizational") 而zhejiang和zhejiang_account是organizational关系 Accountability.create(:parent=> zhejiang, :child=> zhejiang_account, :acctype =>"organizational") 而account和zhejiang_account是functional的关系 Accountability.create(:parent=> account, :child=> zhejiang_account, :acctype =>"functional") 太多了,就到这里,哪位看官有兴趣自己来 china.children.find_by_name("account") zhejiang_account.parents.find_by_name("account") 等等等等 打住,你是否想寻找某一个父中某种类型的子,或者某个子中某个类型的父呢,OK,实在是太简单了,记得我们前面在关系上增加新方法吗,其实,你也可以直接加到模型的类方法,这里我们要寻找的结果是orgnization,所以加到Organization类里面 class Organization < ActiveRecord::Base has_many :accountabilities_as_parent, :foreign_key => 'parent_id', :class_name => 'Accountability' has_many :accountabilities_as_child, :foreign_key => 'child_id', :class_name => 'Accountability' has_many :parents, :through => :accountabilities_as_child has_many :children, :through => :accountabilities_as_parent ######## def self.by_type(type) find(:all, :conditions => ["accountabilities.acctype = ?", type]) end ######## end 看到我加的了吧 china.children.by_type("regional") zhejiang_account.parents.by_type("organizational") 爽吧,美吧 不过记得在写其他代码的时候不要不由自主地has_many :through,你的编译器可不认 |
|
返回顶楼 | |
发表时间:2006-04-27
potian, 在看你最后的使用演示之前我也看得云里雾里的(主要是一开始看到accountability想到的是responsibility然后就困惑模型里这个到底指什么了...) :through一开始我也觉得很方便, 但是后来发现它会屏蔽:class_name和:foreign_key就比较郁闷了. 用has_many模拟的办法比较巧妙啊. 学习~
不过回来说这个数据模型, 地区这棵树和帐户混在一起有点怪怪的, 呵呵. |
|
返回顶楼 | |
发表时间:2006-04-27
不好意思,我指的是财务部门
Accountability是老马的成名作 |
|
返回顶楼 | |
发表时间:2006-04-27
potian 写道 不好意思,我指的是财务部门
Accountability是老马的成名作 失败, 看来得开始看analysis pattern了, 以前总是以为经验不足看不懂. |
|
返回顶楼 | |
发表时间:2006-05-01
我花了2个月出头,从学习ruby到做出一个完全ajax的网站。
做网站以前连对html,javascript,dom,ajax等基本的web概念都非常不熟悉,然而开发进度又比较紧张,所以也无法在将这些基础补充完毕之后再进行开发,只能边做边学。现在回想起来,这样效率也比较高,就是中间过程比较辛苦一些。在去ruby-cn.org这里将中文翻译的ruby参考文档大体浏览完毕,然后就可以看Agile这本书了,看完Agile之后最好就立刻开始动手,做一个简单的程序,比如blog,相册之类。程序完毕之后,可以再返回来阅读programming ruby和ruby for rails,尤其是后者,这样可以加深对ruby和rails本身的认识,同时对于rails的提高建议阅读Rails Recipes进行rails进阶。 |
|
返回顶楼 | |