日历
| |||||||||
| 日 | 一 | 二 | 三 | 四 | 五 | 六 | |||
| 1 | 2 | 3 | 4 | 5 | 6 | ||||
| 7 | 8 | 9 | 10 | 11 | 12 | 13 | |||
| 14 | 15 | 16 | 17 | 18 | 19 | 20 | |||
| 21 | 22 | 23 | 24 | 25 | 26 | 27 | |||
| 28 | 29 | 30 | |||||||
搜索标题
统计信息
- 访问量: 895
- 日志数: 47
- 建立时间: 2008-01-29
- 更新时间: 2008-02-02
我的最新日志
-
我爱Ruby的37个理由
2008-2-02
我不打算浪费时间来谈论Ruby的历史,如果你没有听说过它,你可以去它的主页看看www.ruby-lang.org,或者去它的新闻组comp.lang.ruby。如果你知道Ruby,我将讲述我为什么会喜爱它。(你也可能去我的Ruby主页或者个人主页看看)
1. 它是面向对象的。 这表示什么意义呢?如果问10个程序员,你也许会得到12种结果,你有你的看法,我不会试图去改变你的看法。但是有一点,Ruby提供了对数据和方法的封装,允许类的继承,对象的多态。不像其它语言(C++,Perl等),Ruby从设计的时候开始就是一种面向对象的语言。
2. 它是纯面向对象的语言。难道是我多余?不是这样的,之所以这么说,因为Ruby中一切都是对象,包括原始数据类型(primitive data types),比如字符串,整型,都表示的是一个对象,而不需要Java那样提供包装类(wrapper classes)。另外,甚至是常量,也会被当作对象来处理,所以一个方法的接收者,可以是一个数字常量。
3. 它是动态语言。对于只熟悉像C++,Java这样静态语言的人来说,这是一个重大的概念上的差别。动态意味着方法和变量可以在运行时候添加和重定义。它减少了像C语言那样的条件编译(#ifdef),而且容易实现反射API(reflection API)。动态性使得程序能自我感知(self-aware),比如运行时类型信息,检测丢失的方法,用来检测增加方法的钩子等。在这些方面Ruby和Lisp和Smalltalk都有一些关系。
4. 它是一种解释执行的语言。这是一个负杂的问题,值得重点解释一下,也许这个特点会因为性能的原因而引起从优点变为缺点的争论。对于此,我有几点见解:1.第一:快速开发循环是一个巨大的好处,这要得意于Ruby的解释执行。2.多慢才叫慢呢?在说它慢之前先定一个慢的基准。3.也许有人要批评我了,但我还要说:处理器每年都在变得原来越快。4.如果你真的很在意你的速度,你可以用C开发一部分你的代码。5.最后,从某种意义上说,这是一个还在争论中的问题,没有一个语言天生就是解释型的,世界上没有哪个法律进制开发一个Ruby编译器出来。
5. 它理解正则表达式。很多年之前,正则表达式只是用在UNIX的工具如grep或者sed中,或者在vi中进行一些一定的查找-替换等。Perl的出现解决了这些问题,而现在,Ruby同样也能做到这些。越来越多得人认识到了这种字符串和文本处理技术的难以置信的能力,如果你对此表示怀疑,那么请去看一下 Jeffrey Friedl的书Mastering Regular Expressions,然后,你就应该不会有什么怀疑了。
6. 它是多平台的。 Ruby可以运行在Linux,UNIX,Windows,BeOS?,甚至MS-DOS。如果我没记错,甚至还有一个Amiga 版本的
7. 它是派生来的。这是一件好事情吗?抛去书本上的知识,它是有用的。牛顿曾说过“我如果看得比别人远,那是因为我站在巨人的肩膀上”。Ruby同样也是站在巨人的肩膀上,它借鉴了Smalltalk, CLU, Lisp, C, C++, Perl, Kornshell等的优点。在我看来它的原则包括:1.不要重复制造轮子。2.不要修补没有损坏的东西。3.最后一个也是比较特别的,它能平衡(Leverage )你已有的知识。你了解UNIX的文件和管道,没关系,你可以在Ruby中继续用,你用了两年的时间学习了printf 指示符,不必担心,Ruby中你也可以使用printf。你知道Perl的正则表达式处理,那么你也就学会了Ruby中的正则表达式。
8. 它是创新的。是不是觉得这个和第七条矛盾了?也许是有一部分矛盾,每个硬币都有两面。一些Ruby的特点都是创新的东西,比如非常有用的Mix-in,也许这个特点会被后来的语言借鉴。(注:一位读者指出Lisp早在1979年就有mix-in了,这是我的疏忽;我应该找个更好的例子,并且能确信它。)
9. 它是非常高层次的语言。(Very High-Level Language :VHLL) 这是一个容易引起争论的话题,因为这个术语还没有广泛使用。而且它的意思比起OOP来说还是有讨论余地的。我这么说,指的是Ruby能支持复杂的结构和这些结构的负杂的操作,而需要的指令非常少,这与最小努力原则(Principle of Least Effort)一致。
10. 它有一个灵巧的垃圾收集器。 像malloc和free 这样的例程已经是昨天的恶梦了,你不需要什么回收内存的操作,甚至是调用垃圾收集器。
11. 它是脚本语言。不要因为此就认为它不够强大,它不是一个玩具。它是完全成熟的语言,用它能轻松的完成传统的脚本操作,比如运行外部程序,检查系统资源,使用管道,捕获输出等等。
12. 它是通用的。 Kornshell做的东西它也可以做,C语言做的东西它也可以做的很好。你可以用它写一个只运行一次的只有10行的程序,或者对一些遗留程序进行包装,你想写个web server,或者一个CGI,都可以用Ruby来写。
13. 它是多线程的。 Y你可以用一些简单的API来写多线程程序,甚至在MS-DOS上都可以。
14. 它是open source的。你想看它的源代码吗?可以,你也可以提交补丁,参加广泛的社区,包括它的创造者。
15. 它是值觉得。 Ruby的学习曲线比较低,而如果你翻过了一个坎,你开始“猜测”事情是怎么工作的,而且你的猜测很多时候都是正确的。Ruby坚持最小惊讶( Least Astonishment)的原则。
16. 它有异常机制。 像Java和 C++一样, Ruby 中也有异常机制,这意味着你不必因为返回值而将代码弄得凌乱不堪,很少的嵌套if语句,很少的意大利面条似的逻辑,更好的错误处理。
17. 它有一个高级的数组类:Array。 Ruby中数组都是动态的,你不必像pascal那样在声明它的大小,也不必像C,C++那样为它分配内存。它们是对象,所以你不必关心它们的长度,实际上你不能"走到末尾(walk off the end)"。这个类提供了各种方法,使得你能够根据索引,根据元素来访问数组内容,也可以反向处理数组。你也可以用数作作为set,队列,堆栈等。如果你想用查找表,可以用哈希结构。
18. 它是可以扩展的。 你可以用C或者Ruby来编写外部库(external libraries),同样,你也可以修改已有的类和对象。
19. 鼓励文档编程(literate programming)。你可以在Ruby程序中嵌入注释或者文档,这些文档可以用Ruby的文档工具提取和处理。(真正的文档编程者可能认为这是必须的基本东西吧)
20. 创造性的使用标点符号和大写字母。比如一个方法返回一个boolean型(Ruby中并没有这种说法),那么一般这个方法最后都以问号结尾,如果一个方法要修改接收者本身,或者具有破坏性,则用一个感叹号结尾,简单,直觉。所有常量,包括类名,都以大写字母开头,所有对象属性以@符号开头。这有匈牙利命名法的实用性,但是没有视觉上的丑陋性。
21. 没有保留字。只要语法分析器看不出歧义,就允许用所谓“保留字”作为标识符。呼吸一下新鲜空气。
22. 支持迭代器。这使得你可以给一个数组,list,tree等对象传递一个块,然后对它们的每个元素进行block调用。这个技术值得深入学习。
23. 它的安全性。 Ruby借鉴了Perl中基于$SAFE变量的分层控制机制。这对于CGI程序来说非常有用,可以防止人们攻击web服务器。
24. Ruby中没有指针。 像 Java一样,和C++不同,Ruby中没有指针的概念,所以免除了关于指针语法和调试的头疼。当然,这也意味着最底层的程序开发将会很困难,比如访问一个设备的控制状态寄存器;但是,我们可以用一个C库来调用。(像C语言程序员有时候要使用汇编语言一样,Ruby程序员有时候也要使用C语言来完成一定的任务)
25. 它使得人们专注于细节。 Ruby中有很多同义词和别名,你也许不记得字符串或数组的长度是size还是length,没关系,它们任何一个都可以工作。对于Range来说,你可以使用begin 和end 或者使用 first 和 last,它们也都工作。你想拼写indices,结果写成了indexes,没关系,这两个都一样。
26. 非常灵活的语法。方法调用时候括号可以省略,参数之间只需用逗号分割。类似Perl风格的数组定义可以让你不用全部使用引号和逗号定义一个字符串的数组。关键字return可以生路。
27. 丰富的库函数。 Ruby提供了线程,socket,有限对象持久化,CGI,服务器端可执行的,数据库等其它库函数,还有对Tk的支持等。还有很多其它的库函数。
28. 本身自带调试器(debugger)。在完美的世界中,我们才不需要调试器,但是这个世界不是完美的。
29. 交互式执行。 可以用Ruby像Kornshell那样执行。 (这可能是本页最具争论的一点,我不得不承认,Ruby真的不是一个很好的shell。但我仍然坚持,基于Ruby的shell是一个不错的主意。)
30. 它是简明的。 不像Pascal那样要求if后面跟着then,while后面跟着do 。变量不需要声明,它们不需要类型。返回类型不必指定,关键字return 可以省略,它将返回最后一个表达式的值。另一方面,它也不像Perl或者C那样复杂难懂。
31. 它是面向表达式的(expression-oriented)。 你可以轻易的使用 x = if a<0 then b else c 这样的表达式。
32. 语法砂糖(syntax sugar)。 (像Mary Poppins解释:一勺语法的糖能使语义被接受) 。如果你想对数组x进行迭代,可以用for a in x。你也可以用a+=b代替a=a+b,这都行。很多操作符其实在Ruby中都是方法,这些方法的名字比较直观,短小,有着便利的语法。
33. 它支持操作符重载。如果我没有记错的话,早在很久之前的SNOBOL就提供了这个功能,但是直到C++它才变得流行。虽然它可能乱用而出错,但是这仍是一个非常不错的优点。另外Ruby自动定义操作符的赋值版本,比如,如果你重定义了+,那么,你同时得到了一个+=操作符。
34. 支持无限精度的数字。 有人会关心 short, int, long吗,只需要使用 Bignum就行了,你可以轻松的实现365的阶乘。
35. 有幂操作符。在很久以前,我们在BASIC和FORTRAN中使用它,然而当我们学习Pascal和C之后,我们才认识到这个操作符有多差劲。(我们被告知自己连它是怎么工作的都不知道-它使用了对数,迭代了吗,效率如何?),但是,我们真的关系这些吗?如果是,我们可以重写这个方法,否则,Ruby有非常好的* *(星号之间无空格)操作符可以用。
36. 强大的字符串处理。 If如果你想查找,判断,格式化,trim,定界(delimit),interpose,tokenize,你可以自己选择随便用哪一个来得到你想要的结果。
37. 规则很少引起异常。 Ruby的语法和语义比其它语言有条理,每种语言都有独特的一面,每条规则都会有异常发生,但是Ruby规则引起的异常就少的多了。 -
Rails系列教程(10):Linking Pages Together
2008-2-02
在最前面,我们先要谈一个有关MVC的话题:
MVC中的controller是一个协调者,他可以协调多个view,同样也可以协调多个model,这样的结果就是:
多个Model可以对应一个controller,同样多个view也可以对应一个controller
理解这个结构对开发是有很重要的意义的,注意,这仅仅表示M,V,C的对应关系,而不表示流程
超级连接:
为了说明问题,我们先来建立一个页面goodbye,大家应该很熟悉何如建立了吧,先建立action method,然后写好相应的template,这里的template这样写:
<html>
<body>
<h1>Goodbye!</h1>
<p>
It was nice having you here
</p><a href="/say/hello">Go to Hello</a>
</body>
</html>注意,我们这里使用了一个超级连接,这样就把2个页面连接到一起了,注意href="/xxx/xxx"第一个xxx表示controller name,第二个表示action name。我们使用这样的URL连接将有一定问题,因为我们建立这样的URL的前提是系统约定好了使用这样的格式,而这样的约定是可以改变的,假如约定发生变化,一切都会变化,那我们所有页面的连接都要重新改过,为此,Rails提供了另外一种实现方式,调用 link_to method,这个method是一个helper method,使用方式如下:
<p>Time to say<%= link_to "GoodBye!", :action => "goodbye" %></p>
link_to这个method,这里带上了2个parameters,第一个是用于显示连接的文本,第二个表示连接的内容,这个parameter提供了action的名字,这样,连接也就生成了
我们还可以用link_to弹出一个confirm,做法如下:
<%=link_to "delete", :action=>"delete", :confirm=>"你确定要删除吗"%>
-
Rails系列教程(9):Hello, Rails!(2)
2008-2-02
前面说过<%=%>来生成动态内容,其实ERb还有一种很重要的方式就是<% ruby code %>,来生成动态内容,他们两者的区别在于<%%>不会返回一个值,并用字符串的形式显示出来
<%%>解释并运行里面的ruby code,例如:
<% 3.times do %>
大家好!
<% end %>另外介绍一个有用的方法---“h”,了解html的朋友知道,html语言里面存在一些字符,通过简单的输入得到(这样的字符在html里面被叫做特殊字符),比如输入:
,在html里面要使用"©",输入空格,要使用" ",现在有了h这个method,我们只需要输入我们想要的字符(特殊字符)它会完成转化,例如,最常用的:
<%=h(" 2006
www.xxx.com") %>
我们继续向下面看:
前面说过View和Controller有密切的关系,所以把它们绑定成为一个component(action pack),那么下面就是有关于他们如何紧密接触的一个方面:
定义hello:
class SayController < ApplicationController
def hello
@time = Time.now
end
endhello.rhtml
<html>
<body>
</body>
</html>
结果显示出时间,我们知道对于一个instance variable,它的作用域仅仅限制在class内,外部是不能够应用的,在template里面可以调用@time是因为:controller将它的instance variable注入到了对应的template中了,强调2点,第一,某个controller的instance variable只能在对于的template中访问,注意对应;第二,注入的方向是从controller到template,也就是controller中的instance variable可以在template里面访问
-
Rails系列教程(9):Hello, Rails!(1)
2008-2-02
不论是什么语言,hello world都标志着一个开始,同样,我们来看看Rails的Hello, Rails。我们前面说过,requests被解析,这样就可以找到controller,并且调用controller里面的action method
开始行动:
我们建立好了demo app,同样也要建立controller,还记得我们前面用于启动WEBrick使用到的scrīpt吧,现在建立controller可以使用另外的一个scrīpt:generate
1)建立SayController
D:\demo>ruby scrīpt\generate controller Say
exists app/controllers/
exists app/helpers/
create app/views/say
exists test/functional/
create app/controllers/say_controller.rb
create test/functional/say_controller_test.rb
create app/helpers/say_helper.rb除了这个scrīpt建立一个controller,还可以通过destroy scrīpt来删除一个controller,比如:
ruby scrīpt\destroy controller say
这个时候我们最关注的是 say_controller.rb,它在app目录下面,controllers文件夹里面,controller用于处理进入的requests,每个request被发送到application,然后application回应这次的request,这是一个简单的模型(request and response model),现实的实现不会这么简单,我们看一个URL:
什么是app和controller的分界线?我们在建立app的时候,就给与了一个名字,比如 rails demo,这个时候demo就是我们的app的名字,所以,在demo(包括demo)之前的一串,都是用于标识app的,紧紧的接在app后面的就是controller name,之后的就是action name
添加action
我们知道action是一个特殊的方法,一个controller里面不单单就是一个action,为了处理很多不同的requests,需要使用不同的action,添加一个hello action:
class SayController < ApplicationController
def hello # 新建立的hello action
end
end
大家看看下面的图解,就能很清楚的了解:
每次request来的时候,都会生成一个controller的instance(WEBrick,Mongrel都会)
总结一下URL对于app的映射:
XxxController 对应 Xxx
Xxx (action method) 对应 Xxx
Xxx (app) 对应Xxx
结果就是: http://app/aaa/bbb
aaa对应 AaaController
bbb对应 method bbb
其实更加复杂的情况是建立这样的controller:建立EatApple,这就涉及到一个命名的问题,ruby约定的命名,除了类名其他的用"_"分开,这就使得我们建立起来的文件名(controller的文件名)为:eat_apple,但是Controller为:EatAppleController,我们使用这样的方式访问 http://localhost:3000/EatApple/hello 结果:
Routing Error
Recognition failed for "/EatApple/hello"
使用 http://localhost:3000/eat_apple/hello 结果可以正确访问
这也就是说明,实际上,URL对应的是controller的文件名字,而不是class name
对于action method就没有什么疑惑了,因为不存在命名的问题
现在看看我们的app,输入:http://localhost:3000/say/hello
假如没有定义hello action,结果会显示:
Unknown action
No action responded to hello
我们定义一下hello,结果为:
Template is missing
Missing template ./scrīpt/../config/../app/views/say/hello.rhtml
因为我们为hello定义的仅仅是一个空方法,没有任何内容。在我们身成controller的时候,也在view下面生成了一个文件夹say,这里显示Template is missing是因为在say目录下没有找到hello.rhtml。默认情况下面,xyz action method 会自动寻找 view 下面的对应的controller下面的xyz.rhtml。所谓的rhtml文件其实就是类似jsp文件,这样的文件,里面包含html代码,我们写一个hello.rhtml:
<html>
<head>
<title>Hello,Rails</title>
</head><body>
<h1>Hello from Rails!</h1>
</body>
</html>
结果如下:
即使我们没有定义action,仍然可以访问有关页面,比如说,我在view\say 下面建立了一个 a.rthml,那么就可以通过 http://localhost:3000/say/a来访问,当然这个似乎是有点不太规范的做法
ERb:我们前面说过通过templates可以动态改变内容,其中templates的一种产生动态内容的方法就是ERb
ruby代码被放入 <%= ruby code %>中,这些代码将被解释并且运行,结果被转化成为字符串显示在<%= ruby code%>出现的地方,例如:
<ul>
<li>Addition: <%= 1+2 %></li>
<li>Concatenation: <%= "cow" + "boy" %></li>
<li>Time in one hour: <%=1.hour.from_now %></li>
</ul>注意 1.hour.from_now 表示的是从现在开始的以后1小时后的时间,这里会显示 “Wed Aug 02 11:05:09 中国标准时间 2006 ”,这就牵涉到一个中文问题,有一种解决办法就是在controller下面的application中加入:
class ApplicationController < ActionController::Base
before_filter :set_charset #symbol object,只要下面defined method name和这个一样就可以了def set_charset #和上面的symbol object一致
@headers["Content-Type"] = "text/html;charset=gbk"
end
end这里是要注意的,设置charset为gbk使得API可以显示出中文
ERb is a filter,所以有before_filter。所有的 filters 被放入一个数组中,这个array被叫做the before filter chain,这类的filters,将在action被调用之前运行,添加这样的filters 的方法就是 (1)使用before_filter method添加一个symbol object到数组,这个symbol就说filter的name (2)定义这个filter
@headers["Content-Type"] = "charset=gbk",这里使用instance variable headers来设置Content-Type
我们在添加code的时候,不需要重启服务器,在开发模式(development mode)中,服务器会运行最近更新的文件
-
Rails系列教程(8):Creating a New Application
2008-2-02
现在是一个开始,通过实际的操作让我们更加深入的了解Rails:
Rails使我们仅仅需要“必要”的配置,而不是想其他的工具一样,要完成很多没有必要的配置,我们用rails产生一个完整的app结构,而不要我们自己定义,在适当的位置填充内容,就是程序员的工作了。注意我们前面说的用rails产生一个完整的app结构,其实是这样的,rails在被安装以后,我们就得到了一个命令行工具(command-line tool):rails,通过这个tool我们可以建立一个标准的rails app
具体操作:
使用Rails创建app,我们要建立一个名为demo的app
>rails app
create
create app/controllers
create app/helpers
create app/models
create app/views/layouts
create config/environments
create components
create db
create doc
create lib
create lib/tasks
create log
create public/images
create public/javascrīpts
create public/stylesheets
create scrīpt/performance
create scrīpt/process.
.
.
demo的目录结构:
[app] [components] [config] [db]
[doc] [lib] [log] [public][scrīpt] [test] [tmp] [vendor]
Rakefile README
刚刚开始我们不用关注太多了目录
1)public目录
public目录里面的内容暴露在end users的面前(end users:使用我们app的用户),这个目录关键的文件是dispatcher:dispatch.cgi , dispatch.fcgi , dispatch.rb
dispatchers:接受end users通过browers发送来的requests,并且指引requests进入我们的app
2)scrīpt目录
scrīpt目录里面有一个重要的scrīpt为server,我们这样启动server:
>ruby scrīpt\server(我这里使用的是rails 1.1.4,到2006年7月29日的最新版本)
这样我们就启动了web server,这个web server叫做WEBrick,其实我们会有更好的选择(见本blog《Mongrel---Faster Is Possible》),但是作为学习,WEBrick很不错
注意我们这里启动的时候使用的是ruby scrīpt\server
假如(windows下)这样启动WEBrick
cd scrīpt
ruby server
结果是可以启动的,在browers里面输入http://localhost:3000/进入测试
但是点击上面的 About your application's environment 运行就会出现错误:
正确的运行应该是这样的(必须这样启动WEBrick--->ruby scrīpt\server):
本来以上的内容都已经在以前的文章中强调过,但是,为了让一些没有读过之前文章的朋友不致于迷惑于此,再次说明一下,上图也显示了在winxp sp2下面笔者安装的各个信息,请在学习本文的时候,确定版本差异不大
WEBrick运行之后显示如下信息:
[2006-07-29 16:40:08] INFO WEBrick 1.3.1
[2006-07-29 16:40:08] INFO ruby 1.8.4 (2006-04-14) [i386-mswin32]
[2006-07-29 16:40:08] INFO WEBrick::HTTPServer#start: pid=3552 port=3000注意到最后面的信息 port=3000,3000的端口号是默认的,所以我们可以通过 http://localhost:3000/来访问
开始说了,在学习的时候使用WEBrick还是不错的,因为WEBrick提供了一个控制台,这样我们可以清楚的看见输出的信息,有些web server,比如Mongrel是在后台运行,我们要知道发生了什么事情,就是比较麻烦的事情,我们可以很容易的输出信息到控制台上面,以后就会看到,想要停止服务器,可以通过control+C
-
Rails系列教程(7):Rails and Databases
2008-2-02
Rails可以工作在DB2,MySql,Oracle,Postgres,SQL Server and SQLite databases.除了MySql之外的其他数据库,你必须安装database driver,它一个library,rails通过这个library可以连接和使用database,MySql database driver是纯ruby写的,但是大多数的driver都是用C语言写的,各个database的安装都相似,只是SQL Server有一些不同,如果有需要,请读者自行查阅资料,以后的内容都是基于MySql数据库的 -
Rails系列教程(6):Action Pack
2008-2-02
controller and view :
controller and view 有密不可分的关系,controller为view提供data,controller接受由view产生的页面发出的events因为controller和view的密切关系,rails把他们绑定成一个component---Action Pack
View Support
动态内容的生成:使用controller里面的action method(action也用来控制requests的去向),templates也同样用于产生动态内容,这里主要说明一下templates产生动态内容的2种方法:1)ERb
在view中直接嵌入ruby code,但是有些人认为这是违背了MVC的精髓(the spirit of MVC),因为这使得我们有可能在view中添加本来应该在controller和model中的逻辑(logic),不过维护MVC,是程序员的工作
2)builder-style
builder-style:使用ruby构建xml文档,生成的xml的结构将自动的遵循代码结构(the structure of the generated XML will auto-matically follow the structure of the code)
以后以上的内容都会有具体的实现
Controller:
controller是application的逻辑中心,rails把问题呈现出来,把复杂的实现隐藏在后面,这样使得application容易开发和维护,做application所关注的不单是开发效率,还有一个重要方面就是维护
controller的一些其他的重要的作用:
1)它能将外部requests表示为内部的actions,能够很好的处理对人友善的URL
2)管理caching
3)管理help modules,它用于扩展view-templates的能力
4)管理sessions
-
Rails系列教程(5):Active Records
2008-2-02
Active Records : 被应用于ORM layer
ORM model : tables map to classes, rows to objects, and columns to object attributes
还是要强调一下,a row maps a object, a table maps a class, a column maps a attributeEx:
require 'active_record'
class Order < ActiveRecord::Base
end# work on business logic
order = Order.find(1) # fetch the order with an id of 1
order.discount = 0.5
order.save很显然,这样的实现很直观,不需要考虑到内部如何连接数据库,如何使用SQL语句,一切都变得高效,快速(alige)
-
Rails系列教程(4):Object/Relational Mapping
2008-2-02
ORM:ORM libraries 是把 database tables 与 classes间产生一种mapping(映射),并不像ORM本身表示的Object /Relation Mapping,不是对象和关系的映射,在概念上来说,Relations 更像是 Classes
具体来说说什么是mapping:
假如database 有一个table---orders,那么就会有一个类Order与之对应,我们知道,database约定了table name使用复数,而类不需要,所以,这里才会有单复数的区别,这个不是当当为了满足程序员的习惯,同时是为了满足数据库设计人员的习惯(关于数据库命名《Database Principles Programming and Performance》一书中有提到)
术语的对应关系:
object --- row
attributes用于set,get column
Rails使得我们从table-level 操作转化到 class-level。
这样对描述毕竟还是很难了解一些深度的东西,下面举例:
order = Order.find(1)
puts "Order #{order.customer_id}, amount=#{order.amount}"
我们可以清楚看到前面说过的,order(object)对应的是一些行,这里Order这个class method返回一个order object,这个object可以使用attributes,来access一些columns,注意这里的object可以对应row,也可以对应rows,比如 ōrder = Order.find_al,但是rows不能通过一个object(对应row的)来保存,所以这里Class method返回的是一个collection,这个collection里面保存的是Order类型的object,为了更加详细的说明collection,这里有一个更加容易理解的例子:
读取数据:
Order.find(:all, :conditions => "name='dave'") do |order|
puts order.amount
end
写入数据:
Order.find(:all, :conditions => "name='dave'") do |order|
order.discount = 0.5
order.save #method save()
end
#the objects corresponding to individual rows in a table
总结就是一句话:
So an ORM layer maps tables to classes, rows to objects, and columns to attributes of those objects.
注意,全部的对应关系,都是1对1,一个class对应一个table,一个row对应一个object,一个attribute对应一个column
-
Rails系列教程(3):Database-centric Programming
2008-2-02
执行SQL语句的做法通常有2种:1)在程序里面嵌入sql代码(embed)2)使用preprocessor
1.ruby中使用嵌入sql语句的做法:
def update_sales_tax
update = @db.prepare("update orders set tax=? where id=?")
@db.select_all("select id, amount from orders") do |id, amount|
tax = calc_sales_tax(amount)
update.execute(tax, id)
end
end
其实这样的做法已经比java的做法简单很多了,更不用说是c语言对sql的操作,这种特性不是来自于rails,而是来源于ruby,当然作为层次型语言对平面型数据库的操作,本来就有很多不好的地方,其实,最好的解决应该是把数据库转化成层次型,这样更加直接,方便,能够更好的应对需求变更,但是现在的层次型数据库毕竟还没有兴起,只能看看以后的发展情况了
但是这样的写法实际上是不好的,我们可以看见程序里面有sql,sql被涵盖在程序的可能出现的角落,结果application logic和database logic纠缠到了一起,这样的纠缠带来了错综复杂的关系,有可能造成了这样一种情况,修改了表里的一个属性项,需要修改很多程序的地方,而且这些地方不一定是明显的,这样的方式把数据暴露出来,就像我们使用继承的时候,使用class instance variables而不去使用方法是一样的,结果是恶劣的,当然这样的行为影响的是维护(maintain),同时我也相信,世界上没有系统一次就能开发完善以致于不需要任何维护。其实这也包含了一个复用和封装的问题,一段代码,如果以非methods的形式出现,而是通过copy来实现,那么这样的拷贝会带来很多的麻烦
记住,封装(encapsulation)是解决重复代码的一个很有效的方法,encapulation解决的是:一处修改,处处更新
