不论是什么语言,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和这个一样就可以了
defset_charset #和上面的symbol object一致
@headers["Content-Type"] = "text/html;charset=gbk"
end
end
这里是要注意的,设置charset为gbk使得API可以显示出中文
ERb is a filter,所以有before_filter。所有的 filters 被放入一个数组中,这个array被叫做thebeforefilter 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)中,服务器会运行最近更新的文件