Rails 总结了下 routes 的使用

heroyct · 2018年08月30日 · 最后由 heroyct 回复于 2018年09月10日 · 4126 次阅读

总结了一下目前开发中写 routes 的时候遇到的各种情况以及如何解决的

routes 简介

什么是 routes

简单来说就是把 HTTP Request 匹配到对应的 action(定义在 controller 里)

如何定义

在 config/routes.rb 里面定义,类似于这样

Rails.application.routes.draw do 
  resource :books, only: [:index, :show]
end

如何查看已经定义好的 routes

$ bundle exec rake routes

根据 subdomain 来分配路由

比如网站管理画面希望用 http://admin.your-site/ 来访问

constraints subdomain: 'admin' do
  scope module: 'admin' do
    resources :books
  end
end

这样只有 subdomain 是 admin 的时候才会匹配 admin 下面对应的路由

根据 domain 来分配路由

1. 定义 domain 的匹配

#lib/constraints/domain_constraint.rb

class Constraints::DomainConstraint

  def initialize(domain)
    @domain = [domain].flatten
  end

  def matches?(request)
    @domain.include? request.domain
  end
end

2. 在 config/routes.rb 里面定义对应的 routes

# config/routes.rb:

constraints DomainConstraint.new('app1') do
  resources :app1
end

constraints DomainConstraint.new('app2') do
  resources :app2
end

redirect

get '/test', to: redirect('/to_url')
  • 注意 routes 里面定义的 redirect 的 http status 是 301,而 controller 里面的 direct 是 302
  • 因为对 SEO 有一定影响,如果是永久性的转移建议定义在 routes 或者 nginx 之类的 web 服务器上面

用 routes 定义好的名字

= link_to 'book', books_path
= link_to 'book', controller: "books", action: "index"

用 bechmark 来测试的话,或发现第一种写法要快上一倍
尽量使用定义好的 url_path,也可以用 as 来自己定义名字

get '/books' => 'books#index', as: 'books'

对 url 的参数进行限制

比如 id 只想要整数,可以这样进行限制

get 'books/:id', constraints: { id: /[1-9][0-9]*/ }

只匹配限定的参数

get 'books/:type', constraints: { type: Regexp.union(['type1','type2','type3']) }

限制用户的权限

使用 devise 的话,可以像下面这样限制 admin 权限的用户才可以访问 sidekiq 管理画面

authenticate :operator, lambda { |o| o.admin? } do
  mount Sidekiq::Web => '/sidekiq'
end

将 routes 分割为多个文件

当 routes.rb 太大的时候,我们可能会想要分离为多个文件来方便管理

1. config/routes里面进行如下定义

# config/routes.rb:

Rails.application.routes.draw do
  def draw(routes_name)
    instance_eval(File.read(Rails.root.join("config/routes/#{routes_name}.rb")))
  end

  draw :user

  constraints subdomain: 'admin' do
    draw :admin
  end

  match '*path', to: 'application#render_404', via: :all
end

2. 在 config/routes/ 文件夹下面添加 routes 定义文件

文件结构

config/routes/
├── admin.rb
└── user.rb

对应的文件

# config/routes/user.rb
resources :books
# config/routes/admin.rb

resources :authors

不错,插眼

这样分文件的话 要注意配置一下 eager load path

@matrixbirds

这样分文件的话 要注意配置一下 eager load path

能详细说一下吗?目前用的是 rails 4.2,没有进行其他配置

是这类问题吗? https://blog.arkency.com/2014/11/dont-forget-about-eager-load-when-extending-autoload/ https://stackoverflow.com/questions/48538755/eager-load-all-classes-before-routes-rb-being-loaded

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