由于路由这节的内容有些多,所以,我把它分成两节来写。
阅读本文收获- 知道
_path
与_url
都是Rails的路由。作用一样。 - 知道
xx_path
的来历。这样看代码时不会发蒙。 - 知道 路由的
namespace
- 知道 路由的不同写法. 可读性的意义。
- 第一次写一个接口。(你会发现是如此的简单!)
- 知道
root_path
与match
路由。 - 知道哪些路由是千万不要学的。 大坑啊!
跟 茴香豆的四种写法<a> 标签的下面四种写法, 都是一样的.
<!-- 下面四种写法,都会产生 同样的<a>内容 -->
<a href='/books/new'>跳转到新建页</a>
<a href='<%= new_book_path %>'>跳转到新建页</a>
<%= link_to "跳转到新建页", '/books/new' %>
<%= link_to "跳转到新建页", new_book_path %>
它们生成的HTML内容都是一样的:
_path
是从哪里来的?
它来自于config/routes.rb
中对于route的定义。
new_book_path 是动态生成的方法,返回一个URL(可以认为是字符串)
同理, 还可以从下面的配置文件看出,除了 new_book_path
外,还有其他的url: edit_book_path
, books_path
, 以及 book_path
, 和第一行的 list_books_path
_path
与 _url
有什么区别?
没有区别。 books_path
与 books_url
一模一样。
/books/new
就很好了,干嘛要写成 new_book_path
?
太长不看版: 为了我们的方便。
详细答案:
一个例子,我们如何编辑某个book?
/books/1/edit
(编辑id = 1 的book)
写成ruby代码: (假设book_id = 1), 传统形式是:
"/books/" + book_id + "/edit"
"/books/#{book_id}/edit"
( string interpolation 插入插值 )
在实践中,我们发现上面这两种形式,都是外行的风格(比如,之前做java/javascript 的同学,来写ruby , 就是这个风格)
下面是 Rails风格(把可读性发挥到极致)的写法:
edit_book_url({:id => book_id})
这个写法,可以引申成: (ruby方法最外层圆括号可以省略, 方法的最后一个参数如果是hash 的话, {} 也可以省略)
edit_book_url :id => book_id
继续省略:
edit_book_url book_id
可读性极其重要。
例如,我们声明: book_id = 1
, 那么,就可以写下面3 种路由:
"/books/" + book_id + "/edit"
"/books/#{book_id}/edit"
edit_book_path book_id
# rails的推荐写法。
第三种形式是可读性最好的,也是Rails程序员最喜欢读写的。
所以,记住: 希望生成某个url:
/books/list?a=1&b=2
就可以写成:
list_books_path(:a =>1, :b => 2)
namespace 也就是一个前缀. 有2种常见用途:
- 不同角色使用的url, 例如::
/books
普通用户看到的url/admin/books
专门给管理员访问的url , 加上了/admin
前缀
- 对于接口的url:
/interface/books
加上了/interface
前缀, 大家一看到这个url 就知道, “哦!这是个接口!”。( 让这个url 有“自解释”的能力。) 同时,更方便我们在日后的优化中(例如 nginx 中的缓存配置等)做处理。
由于接口越来越重要(任何一个mobile app都会用到), 所以我这里为大家举个例子。
使用前缀实现接口的例子1. 添加路由:
在config/routes.rb
中,增加下面红色边框的语句:
2. 添加controller:
新建一个文件: app/controllers/interface/books_controller.rb
注意:
- 它跟
app/controllers/books_controller.rb
不是一个文件. render :json => {}
表示 返回一个json- 继承的类是
ActionController::Base
- 类名前面有个
Interface::
前缀.
class Interface::BooksController < ActionController::Base
def all
render :json => {
:name => '小王',
:sex => 'male',
:age => 18,
:address => '北京市朝阳区...'
}
end
end
3. 打开浏览器, 可以看到结果
打开 /interface/books/all
, 可以看到结果: 一个json.
root_path
决定了项目根目录 ( /
)的页面是哪个.
下面我们为当前项目增加一个root_path
1. 修改路由文件:下面的路由表示,对于 根目录的请求 , 会由 books
controller的 welcome
action 来处理。
Rails.application.routes.draw do
# 根路径
root :to=> 'books#welcome'
end
2. 修改对应的controller
app/controllers/books_controller.rb
class BooksController < ApplicationController
# 增加这个action, 它专门为根目录准备
def welcome
end
end
3. 修改对应的view:
app/views/books/welcome.html.erb
<h1>欢迎来到Rails的世界</h1>
<p>Ruby 让编程变得快乐。</p>
4. 访问浏览器。 /
现在,访问咱们的根路径 /
, 就可以看到结果了: (注意: 由于我们没有在 resources :books
中配置 get :welcome
, 所以,我们访问 /books/welcome
是会报错的)
match
随着RESTful 的崛起,这个路由越发显得过时。但是可能在一些遗留项目中会出现。
在目前的Rails4 中, 它的写法如下:
match
: 指定了所匹配的url
to
: 指定了由哪个controller#action
处理via
: 这个请求,是get
还是post
.
Rails.application.routes.draw do
# 直接指定一个url , 由哪个controller#action 来处理。
match '/welcome_you', to: 'books#welcome', via: [:get, :post]
end
现在,访问 /welcome_you
就可以看到结果了。
今天通过两个页面的跳转,学习了路由。
resources
, 重中之重。- 可以加上
namespace
- 可以看懂:
match …
- 其他的,
嵌套的路由
,resource
( 单数), 都不用看。
不要使用嵌套路由,太傻了.嵌套路由的例子:
中国(86)-辽宁省(041x)-沈阳市(010)-和平区(1)
路由可以是:
/countries/86/provinces/041x/cities/010/districts/1
resources :countries do
resources :provinces do
resources :cities do
resources :districts
end
end
end
不要写的这么傻。 不要这么一层一层的下来。 这个是反人类的实现模式。 (我不明白Rails官方干嘛要搞这么一个东西出来,反正我在开源项目中几乎看不到这样的写法)
district
的id是固定的,有它一个就足够了。 所以,我们只要写:
/districts/1
就可以查询到: id = 1的 district
其他形式的,都不用专门学。
遇到的时候,能看懂代码就可以。
本节源代码本节中的例子,对应的源代码,可以来这里下载:
https://github.com/sg552/rails_lesson_2_route
本节对应的ppt, 可以来这里下载:
热门评论
讲的还不错。入门够了
虚拟机安装系统不比双系统更方便吗?<br /><br />还是申请一下,别这么严重鄙视我们用Mac的用户,用mac照样可以学习ruby别搞得非要在linux系统上,<br /><br />装个双系统很费时间和精力,现在搭建一个虚拟环境都很快捷满足,<br /><br />别在这里误人子弟