Rails Rails 路由学习

monsterooo · 2019年06月26日 · 最后由 monsterooo 回复于 2019年06月26日 · 3321 次阅读

路由相关的类和模块在命名空间 ActionDispatch::Routing::Mapper 中,这里我给一个它的链接方便在学习时查看

match

匹配一个 URL 模式到一个或多个路由

基础使用

# 匹配格式为 :controller/:action. 请注意这样使用路由不能带参数
match 'account/setting', via: :get
Prefix Verb URI Pattern Controller#Action
account_setting GET /account/setting(.:format) account#setting

带参数的路由

# 带参数的路由必须指定 :to 参数, 他才能正确匹配到指定的 controller 和 action
match 'account/setting/:id',  to: "account#setting", via: :get
Prefix Verb URI Pattern Controller#Action
GET /account/setting/:id(.:format) account#setting

在路由匹配中使用通配符并且映射到params

match 'songs/*category/:title', to: 'songs#show', via: :get
Prefix Verb URI Pattern Controller#Action
GET /songs/*category/:title(.:format) songs#show

上面的通配符路由会将songs/rock/classic/stairway-to-heaven路径做匹配和映射

<ActionController::Parameters {"controller"=>"songs", "action"=>"show", "category"=>"rock/classic/abc", "title"=>"stairway-to-heaven"} permitted: false>

路由映射到 controller 和 action 的几种写法

# 短写形式, match的第一个参数传递一个hash用来映射对应的路由和控制器
match 'photos/:id' => 'photos#show', via: :get
# 我们上面一直使用的正常模式(比较直观)
match 'photos/:id', to: 'photos#show', via: :get
# 冗余模式, 所有的参数都通过options来指定
match 'photos/:id', controller: 'photos', action: 'show', via: :get

除了以上match的几种使用方法外,还可以指定兼容Rack方式的路由

match 'photos/:id', to: -> (hash) { [200, {}, ['Coming soon']] }, via: :get

match options

:controller

路由对应控制器名称

:action

路由对应控制器里的方法名称

:param

可以用于覆盖资源默认的:id参数,一但覆盖你可以在控制的方法中使用params[:param]去访问

resources :photos, param: :title
Prefix Verb URI Pattern Controller#Action
photos GET /photos(.:format) photos#index
POST /photos(.:format) photos#create
new_photo GET /photos/new(.:format) photos#new
edit_photo GET /photos/:title/edit(.:format) photos#edit
photo GET /photos/:title(.:format) photos#show
PATCH /photos/:title(.:format) photos#update
PUT /photos/:title(.:format) photos#update
DELETE /photos/:title(.:format) photos#destroy

嗯我们看到之前默认:id已经被替换为了:title

为了更好配合上面路由的使用方法,你还可以覆盖对应模型的to_param方法,去构造符合路由的 url

class Photo < ActiveRecord::Base
  def to_param
    name
  end
end

photo = Photo.find_by(name: 'ruby-china')
photo_path(photo)  # => "/photos/ruby-china"

:path

路由的前缀

:module

控制器的命名空间,这里暂时还没懂。稍后补上

:as

设置生成路由辅助函数的名称

match "account/setting", via: :get
match "account_as/setting_as", as: 'setting', via: :get
Prefix Verb URIPattern Controller#Action
account_setting GET /account/setting(.:format) account#setting
setting GET /account_as/setting_as(.:format) account_as#setting_as

通过上面的输出可以看出,我们将account_as/setting_as路由的生成函数定义为了setting, 在代码中就可以这样使用setting_url setting_path

:via

定义路由所匹配的动作 (verbs), 相关动作资料可以看这里

match 'path', to: 'c#a', via: :get             # get 
match 'path', to: 'c#a', via: [:get, :post]    # get/post
match 'path', to: 'c#a', via: :all             # all http verb

:on

可以为 resource(s) 定义的资源增加:member, :collection, :new路由。请注意这个必须在resource(s)的 do 语句块中使用

resources :photos do
  match 'preview', to: 'photos#preview', on: :new, via: :get
  match 'preview', to: 'photos#preview', on: :member, via: :get
  match 'preview', to: 'photos#preview', on: :collection, via: :get
end

也等同于如下书写方法

resources :photos do
  member do
    match 'preview', to: 'photos#preview', via: :get
  end
end
Prefix Verb URIPattern Controller#Action
preview_new_photo GET /photos/new/preview(.:format) photos#preview
preview_photo GET /photos/:id/preview(.:format) photos#preview
preview_photos GET /photos/preview(.:format) photos#preview

:constraints

可以使用正则表达式或者一个可以响应matches?方法的对象来对参数进行约束

match 'account/setting/:id', constraints: {id: /[A-Z]\d{5}/},  to: 'account#setting', via: :get # 约束 /account/setting/A12345
match 'account/setting', constraints: { format: 'json' }, to: 'account#setting', via: :get # 这个不是太懂!
class Whitelist
  def matches?(request) request.remote_ip == '1.2.3.4' end
end
match 'account/setting', to: 'account#setting', constraints: Whitelist.new, via: :get
Prefix Verb URIPattern Controller#Action
GET /account/setting/:id(.:format) account#setting {:id=>/[A-Z]\d{5}/}
account_setting GET /account/setting(.:format) account#setting {:format=>"json"}
preview_photos GET /account/setting(.:format) account#setting

:defaults

设置默认params的值

match 'account/setting', to: 'account#setting', defaults: { id: 'hello' }, via: :get

params 输出:<ActionController::Parameters {"id"=>"hello", "controller"=>"account", "action"=>"setting"} permitted: false>

总结:以上我们学会了match方法的基础使用和它的一些选项,在往后的使用中更能得心应手。关于get, post, delete, put其实也是调用的match方法

感谢阅读,原文链接喜欢可以 star 哈

用 resources 不要用 match,你这个扒开的教程好老

yfscret 回复

resources 还是依赖于 match,当了解了 match 理解 resources 那不是更容易吗?

需要 登录 后方可回复, 如果你还没有账号请 注册新账号