Skip to content

203 Routing in Rails 3

203: Routing in Rails 3
(From asciicasts.com and Railscast )
Translated by Yinghai. Please contact zyinghai at gmail.com regarding this translation.
翻译的比较急,如有问题,请联系zyinghai at gmail.com

这一集我们继续研究Rails的新特性, 这次我们看一下Rails 3的路由. Rails 3提供了一些新的API和新的功能来定义路由. 为了更好的演示,我们先建立一个detour应用。

rails detour

建立好应用之后,我们可以打开config/routes.rb文件看一下. 默认的文件包含了一些演示新API的文档和例子,当你有空的时候,这些都值得一看。 我们先删掉自带的文档,换上老的格式,再来对比一下Rails 3新的用法。

/config/routes.rb

Detour::Application.routes.draw do |map|
  map.resources :products, :member => { :detailed => :get }
  map.resources :forums, :collection => { :sortable => :get, :sort => :put } do |forums|
     forums.resources :topics
  end

  map.root :controller => "home", :action => "index"

  map.about "/about", :controller => "info", :action => "about"
end

以上是需要转化的老格式。

我们先从这一个开始:

map.resources :products, :member = { :detailed =>:get }

这个路由有一个product资源,和一个叫做detailed的附加action,可以通过Get方法请求。

Rails 3第一个值得注意的改变,就是我们不再使用map对象,取而代之的是在routes.draw块里面直接调用resources。resources包括的:member和:collection 动作,可以通过一个块来定义, 上述的路由可以新格式是这样:

resources :products do
  get :detailed, :on => :member
end

下面,我们来看以下更复杂的路由:

map.resources :forums, :collection => { :sortable => :get, :sort => :put } do |forums|
  forums.resources :topics
end

这个路由,在forum资源里面,我们有两个额外的:collection动作,还有一个嵌套的Topic资源。新的API中,可以写成这样:

resources :forums do
  collection do
    get :sortable
    put :sort
  end
  resources :topics
end

以上代码在一次展示了取消map.resources,直接用resources块。我们有两个collection动作,尽管我们可以像第一个例子中detailed动作一样使用:on,但我们这里用collection块达到了同样的效果 (member动作也可以使用member块)。任何在这个块里面定义的路由,都会作用在forums的集合上。在我们的例子中,我们定义了两个,一个是GET方法的sortable和PUT方法的sort。

至于嵌套的topics资源,我们可以在forums的块里再次调用resources,起到嵌套的效果。

下一个路由,我们看一下怎么定义root的控制器和动作。

map.root :controller => "home", :action => "index"

这里,我们可以直接调用root,用:to来定义要转到的动作,控制器跟动作之间,可以用#来区隔。

root :to => "home#index"

用一个#分隔的字符串来定义控制器跟动作,是Rails 3的新特性之一。我们可以用类似的格式来定义named路由。

map.about "/about", :controller => "info", :action => "about"

Rails 3中改写成这样:

match "/about" => "info#about", :as => :about

没有:as参数,这个路由就是单纯的转向”/about”, 加了:as 之后,在我们的应用里面可以使用about_path或者about_url。

新功能

从上面的例子可以看出,只需要微小的改动,就可以从老的API转化到新的API,但是真正吸引人的是新API提供的一些新功能,下面我们来看其中的一部分。

可选参数

前一个版本就已经有对可选参数的支持,但是用法比较麻烦,下面我们来看一下Rails 3中怎么使用。

我们建立一个info控制器和about动作来展示可选参数。Rails 3支持用rails g来作为rails generate的快捷方式。

rails g controller info about

我们可以用rails s快捷方式来启动服务器

rails s

现在我们打开http://localhost:3000/about, 我们会转到之前已经在路由配制文件里面定义的info#about动作。

假设我们下一步想要添加对pdf格式的支持,可是现在打开http://localhost:3000/about.pdf的话,我们会看到一个路由错误,提示没有定义路由。
在路由文件里,我们可以添加一个format参数。

match "/about.:format" => "info#about", :as => :about

如果我们刷新页面,这次会得到应用找不到template错误。

我们已经解决了之前的问题,但是format参数不是可选参数,如果我们返回之前没有.pdf后缀的页面,我们会遇到路由错误,我们可以做简单的改动,只需用括号括起来,就可以让format变为可选参数。

match "/about(.:format)" => "info#about", :as => :about

然后我们可以正常的打开http://localhost:3000/about 或者 http://localhost:3000/about.pdf。

下面,我们来看一下怎么使用更为复杂的可选参数,例如,我们现在有一个博客应用,我们想要在网址中,用可选的年月日来过滤一段特定时间的贴子。
我们可以用下面的路由达到这个效果,主义括号可以嵌套起来定义多个可选参数。

match "/:year(/:month(/:day))" => "info#about"

在view中,我们添加一些调试信息,来检查传入的参数:

/app/views/info/about.html.erb

<h1>Info#about</h1>
Find me in app/views/info/about.html.erb
<%= debug params %>

下面,如果我们传入year参数,about动作会收到我们传入的值,month和day参数也是如此。

这个路由是比较宽泛的,如果我们传入,例如http://localhost:3000/foo/bar,这样的参数也会被传到控制器,很显然,想要符合日期规范的参数,我们可以用constrains来达到这样的目的。

Constraints
Constraints 就是Rails 2中的requirements. :constraints可以传入一个hash来限定匹配。以下的例子用四个数字来限定年,两个数字来限定月和日。

match "/:year(/:month(/:day))" =&gt; "info#about", :constraints =&gt; { :year =&gt; /\d{4}/, :month =&gt; /\d{2}/, :day =&gt; /\d{2}/ }

添加了这个constraint之后,我们再看一下/foo/bar路径,这次我们得到了一个无法匹配的错误。

我们现在做的,Rails 2的requirements都可以做到。但是Rails 3的Constraint更加强大。
例如,我们可以用user_agent参数来限制一些浏览器的访问,以Firefox为例。

match "/secret" => "info#about", :constraints => { :user_agent => /Firefox/ }

如果我们用Safari, Chrome或者Opera访问页面,我们会看到一个匹配错误。但是Firefox可以正常浏览。

我们也可以添加一些更有用处的constraint比如主机名。

match "/secret" => "info#about", :constraints => { :host => /localhost/ }

使用这个constraint,我们可以通过http://localhost:3000/secret来浏览网页,但是用ip地址将会返回错误( http://127.0.0.1/secret ),其实两个地址本质上都是一样的。这个功能可以用来限制某些二级域名的访问,目前这一部分还在开发中,在以后的版本中,constraint可以传入:subdomain参数。

如果我们有多个路由同时使用一个constraint,会造成很多代码的重复。我们可以用constraints方法把这些路由放到一个块中来降低代码重复。

constraints :host => /localhost/ do
  match "/secret" =>; "info#about"
  match "/topsecret" => "info#about"
end

还有很多constraint的高级功能,就不在这里一一赘述了。

Rack路由

因为时间的关系,我们没办法涵盖所有Rails3的路由改进,我们会在未来的视频里慢慢接触。 我今天想介绍的最后一个功能,是Rails 3路由与Rack的集成。
通常我们将地址匹配到一个控制器和动作,但是我们也可以匹配给一个Rack应用,这是一个非常强大的功能,我用一个简单的Rack应用来展示这个功能。

match "/hello" => proc { |env| [200, {}, "Hello Rack!"] }

如果你不是很熟悉Rack,可以看一下第151集视频,我们上面代码就是返回HTTP成功代码,和很简单的内容。

我们访问 /hello 就可以看到“Hello Rack!,以此我们可以看出Rack工作正常并响应请求.你可以用这个强大的功能将路由转到不同的应用。比如可以将路由匹配到Sinatra应用。

Rails 3的路由功能带来了很多令人振奋的可能性,尽管今天我们只是大体地介绍了一下,以后我们会详细的介绍一些具体用法。

如果你需要更多Rails 3的路由信息,可以参考Yehuda Katz的博客和RailsGuides.

Please contact zyinghai at gmail.com regarding this translation.
翻译的比较急,如有问题,请联系zyinghai at gmail.com

Dreamhost部署 Ruby on Rails

建好数据库,用git在dreamhost账号里面clone一个项目目录。
然后添加域名,目录指向public子目录。
钩上ROR选项后,点fully host domain。

不幸的是,启动总有问题。
于是我做了下面几件事情。

1 把rails 2.3.5 冷冻进项目目录
rake rails:freeze:gems

2 设置数据库
database.yml
production:
adapter: mysql
encoding: utf8
database: waimai_hailizi
host: mysql.*******.net
username: ********
password: ************

3 建立数据库表
rake –trace db:migrate RAILS_ENV=production

4 配制环境 config/environment.rb
RAILS_GEM_VERSION = ‘2.3.5′ unless defined? RAILS_GEM_VERSION
ENV['RAILS_ENV']=’production’

if ENV['RAILS_ENV'] == ‘production’ # don’t bother on dev
ENV['GEM_PATH'] = ‘/home/hailizi/.gems’ + ‘:/usr/lib/ruby/gems/1.8′
end

5 设置gem的安装目录,以及
export PATH=”$HOME/.packages/bin:$HOME/.gems/bin:${PATH}”
export GEM_HOME=$HOME/.gems
export GEM_PATH=”$GEM_HOME:/usr/lib/ruby/gems/1.8″

参考这里

6 安装所需要的gem
gem install formtastic

7将gem也冷冻到项目目录里
rake gems:unpack

8 重启服务
touch tmp/restart.txt

然后竟然神奇可以用了。。YAY~~

Ubuntu 9.10

D-Link DWA 140:
Add blacklist rt2800usb to /etc/modprobe.d/blacklist.conf

Compiz:
apt-get install compizconfig-settings-manager

Terminus:
apt-get install xfonts-terminus

Extras:
sudo apt-get install ubuntu-restricted-extras

英文环境中文配置:
cd /etc/fonts/conf.d/
sudo ln -s /etc/fonts/conf.avail/69-language-selector-zh-cn.conf
sudo ln -s /etc/fonts/conf.avail/99-language-selector-zh.conf

两年多

自从07年不写东西到现在,已经过了两年多了:
两年前,我可以四舍到20来岁的,两年后,我只能五入到30来岁。
两年前,我还是无忧无虑的大学生,两年后,我成了终日碌碌的工薪族。
两年前,我有加拿大的暂住证,两年后,我拿了加拿大的户口本。

两年前,是独行,两年后,是人夫。

我开的不是Yinghai.Org, 是寂寞

“哥们,你抽得不是烟,是寂寞”

不知道从什么时候,网络开始流行这句话.山寨版应声而起, “你X的不是XX,你X的是寂寞”

我也山寨一下流行的话吧。

Yinghai.Org其实4,5年前就被我买了,用Wordpress, 断断续续的码字,也写了不少东西。

那个时候想写一个自己的blog程序,于是关了网站,自己闷头闭门造车。

东拉西扯的学了不少新东西,各种语言,技巧,构架,库。。。

从头开始做了一个,觉得不好,有用Liferay构建了一个,又觉得受制于平台。

两年过去了,自己还没用上自己写的blog。

原因很简单,就算我是诸葛亮,也比不过Wordpress得千千万万个臭屁匠。

何况我自己本身是臭屁匠,开源社区人人都是诸葛亮。

虽然在这个过程中,学到了不少东西,

可是回头一看,WP已经长足发展。

于是长叹,我写得不是程序,是寂寞。。。

Yinghai.Org重新开了,转了一大圈,还是用的WP.

希望新朋友老朋友还能常来看看。

注:当然,我不寂寞,老婆一直闹着让我写她,一点都不寂寞。

Tagged

20年最强对话

2007,史蒂夫乔布斯和比尔盖茨的对话。
Continue reading ›

Ubuntu下播放rmvb等

这里 关于Resitricted Format
还有
这里  关于Medibuntu的

然后卸掉原装的Totem,安装Totem-xine
就可以了

昨天梦的题目

昨天梦的题目是。
陈XX适合当高中老师嘛?
陈XX是初中老师,初中我有两个陈老师,这里说的是教语文的陈XX老师
她教语文有自己独特的一套办法,我到现在的初中语文书被别人看到都会惊叹。
因为每一页都满满的字,课文每一行与每一行之间都写满了字。
可后问答题的答案,什么本文反映了什么中心思想啥的。
他都念给我们,然后一屋子80多个人齐刷刷的抄在空白的地方。
古文就更严重了,每个字都解释的清清楚楚。
优点就是,考试的时候一本书,背去吧。
前两天,一人问我,岸芷汀兰里的芷什么意思,
我不假思索就说出自初中学过的岳阳楼记,然后芷是一种香草。
除了感叹自己记忆里超群之外,
想得跟更多的是当时陈老师惩罚记学生的名言,或者口头禅
谁抄下来的东西记不住,就会被勒令:
写检查,家长签署50字意见。。
当时难为了多少无语的家长阿。。

昨天梦到了陈老师跟初中同学,一起被搬到高中去了。
运行状况不良,于是觉得陈老师不适合教高中。
当然了,陈老师恐怕早已退休了。

郑园结和我[2]

小的时候无论家长还是老师还是读物,都鼓励孩子多问问为什么,我也因此拥有过一套10万个为什么,
但是小孩子的问题,无外乎水开了为什么能把盖子顶开,苹果为什么落在地上之类。
再严重点就是问问我是从哪里来的阿,为什么要去垃圾箱捡我阿之类的。
人长大了,明白了水蒸气,万有引力,明白了人是怎么来的,问为什么反而相对少了。
我觉得,人思想成熟了,能独立思考了,才是最需要问为什么的时候,
不然活着就有了惯性思维,思维的定式让人有时候不能一下子接受某些东西。
除非全世界80%的人都认同某种观点了,他也能接受了,不过与其说接受,不如说新的思维定式又形成了。

我妈有的时候对待某些问题就有这样的定式,当然她大部分时候都很好,不然也不能当斑竹这么新潮的东西。
说她有定式,是因为我以前受到郑渊洁跟比尔盖茨影响说我不想上学的时候,
她的每次反应都一样,先是眉头一皱,然后像得知混世魔王降临般的啊一声,
然后开始愁眉苦脸的念叨,不上学怎么行啊,不上学以后怎么办啊,不上学干吗去阿,云云。。
后来我我上大学了,也听过她类似的语气说别人,不上大学以后怎么办啊,不工作以后怎么办啊。。之类
我承认每个父母都是疼爱自己的孩子,希望自己孩子好的,我妈妈也跟大多数妈妈一样。
虽然有某种定式,但始终都是那个善意的出发点。

郑渊洁跟一般父母不一样,他自己没上完小学,后来也没有他儿子上。
他自己不上,是因为他调皮捣蛋,老师让写早起的鸟儿有虫吃的作文,
多么正常的作文题目阿,教育孩子要勤劳早起,这样才能有吃的,多么朴素的观点阿。
可郑渊洁非要多此一举的想一想自己是虫还是鸟,很不幸他选择做虫,于是写作文呼吁,早起的虫子有危险。
受了老师批评也就算了,他偏不服,又没有能力反抗,于是在课桌洞里放了个鞭炮,被开了。
他爸陪他拿着检查找了不知道多少次老师校长,就是不要他,于是他爸爸只好开始自己教他了。

他儿子不上,也是因为他。他觉得作业跟考试成绩是着世界上最不重要的事情,
所以经常帮他儿子做作业,有一天,他发现以他童话大王的想象力写的作文,竟被老师打个红叉退回来重写。
他想为什么他代写的作文会被退回来,为什么要每个孩子都写一样的老三段,为什么孩子要这么教呢,
万一他儿子要是有点想象力,长期受这样的限制,慢慢不也就没了吗,不也就跟别人一样,有思维定式了吗。
为了寻求这些为什么的答案,他买了初中到高中所有的课本跟教参,从头到尾的看了两边,发现的确有方法和内容上的各种不当和缺失。
于是自己以童话的方式,重写了这些教科书,作文课是舒克给你一枝神来笔,有五角飞碟折腾数理化世界,还有性知识课本,你从哪里来我的朋友。
给我感触最深的是他写了皮皮鲁和419宗罪,把中国刑法419条刑事犯罪用儿童可以接受的语言写出来,
还写上给儿子的寄语,儿子:老爸希望你在人生的道路上远离这419宗罪。
现在的孩子多么缺少这方面的知识阿,我上小学上初中的时候,校园简直就是江湖,
一个家里有钱的同学有天下午是被人脱走李宁只穿裤衩来学校的,法律的意识,可以让坏学生收敛,让好学生知道怎么保护自己。
更是构建法制社会和谐社会的起点。可惜就是硬硬的缺失了。。

当然了,不是所有的人都能有郑渊洁这样的能力跟精力教育自己的孩子。
鲁豫也说他的教育方法不适合所有的人,我妈也能列举不让孩子接触别的孩子的一大堆缺点。
我觉得,是重点放错了,研讨郑渊洁对不对,孩子该不该上学,不上学好不好,意义都不大。
试想假如学校教的让郑渊洁满意了,他还会自己教儿子吗。
我身体中作为愤青的那部分细胞觉得,我要是处于郑渊洁的位置,一定要上蹿下跳的求索,改变这个世界,把孩子解脱出来。
虽然郑渊洁比愤青的我自私,只照顾自己的孩子了,但是愤青的我比郑渊洁愚蠢,求索有结果了,孩子都老了。

以后我自己的孩子,我还是会把他送去学校吧,毕竟早恋阿什么的这种机会转瞬即逝的。
不过我的孩子要给我说不想上学了的时候,我一定天上地下问一圈为什么。
然后再像得知混世魔王降临般的啊一声。

全文完

郑渊洁和我[1]

其实我们没有任何的直接联系,我是他的一个读者而已.
名字起得暧昧,用来突出郑渊洁对我的影响很大这个重点.
很早就看童话大王了,好像大概小学的时候.
小时候,爸妈很开明,鼓励我读各种各样的书.
很小我就有一书架子的课外书了.
订阅的杂志有童话大王,故事大王,还有少年科学可以看.
再小的时候还有笑话大王跟幽默大师,
去姥姥家,偶尔可以看到故事会,
这么多杂志里面,觉得童话大王是最好看得,
因为故事大王好像情结也不怎么连贯,短篇比较多,
而且好像我心理成长的比较快,看故事大王觉得里面的东西稍显幼稚了.
少年科学我比较喜欢,里面邮购篇有好多好玩新奇的东西,比如天文望远镜.
垂涎以久却不能得到,于是就会觉得是一本看了会遗憾的杂志.

童话大王不一样,语言亲近少年,故事稍有深度,比较接近社会.
连载篇又能吸引我的注意力,坚持不懈地一期一期看下去.
妈妈还去北京还买了童话合订本,郑渊洁跟皮皮鲁鲁西西对话录,
等等杂志上看不到东西,还有郑渊洁品牌的笔袋,更是被我当作至宝.
后来一直被我带到了加拿大来.

不过郑渊洁到我初二的那段时间,宣传上学不好论.
于是他的作品被当作了我们家的禁书.
好像我们家不准我看的书很少. 初一初二才多大阿,我就可以去姥爷家看红楼梦西厢记故事会等等
那些隐隐约约描写些男女的书了. 那些没有被禁.
郑渊洁的不让看了,跟郑渊洁一起的还有一本比尔盖茨的回忆录.
因为他也宣扬了上学不好的思想,以至于我经常理直气壮的到处说我不想上学了.

现在想想,可能因为他儿子跟我同年,他儿子6年级后不上学了.
他刚刚接触不让孩子上学这个领域,可能各方面压力也比较大.
借助自己的书宣传一下自己的主张. 不过,这一宣传,
让我从此再也没有看到过郑渊洁纸媒的文字.

知道最近才又更全面的了解他。
小时候只是看他的作品,对他一无所知。
因为一直觉得他不让孩子上学,肯定很叛逆,锋芒毕露,针砭时弊那种类型。
结果发现他本人性格很温和,不知为什么我一直都对性格温和的人抱有强烈的好感。
于是就多了解了一下他。