总结了一下目前开发中写 routes 的时候遇到的各种情况以及如何解决的
简单来说就是把 HTTP Request 匹配到对应的 action(定义在 controller 里)
在 config/routes.rb 里面定义,类似于这样
Rails.application.routes.draw do
resource :books, only: [:index, :show]
end
$ bundle exec rake routes
比如网站管理画面希望用 http://admin.your-site/ 来访问
constraints subdomain: 'admin' do
scope module: 'admin' do
resources :books
end
end
这样只有 subdomain 是 admin 的时候才会匹配 admin 下面对应的路由
#lib/constraints/domain_constraint.rb
class Constraints::DomainConstraint
def initialize(domain)
@domain = [domain].flatten
end
def matches?(request)
@domain.include? request.domain
end
end
# config/routes.rb:
constraints DomainConstraint.new('app1') do
resources :app1
end
constraints DomainConstraint.new('app2') do
resources :app2
end
get '/test', to: redirect('/to_url')
= link_to 'book', books_path
= link_to 'book', controller: "books", action: "index"
用 bechmark 来测试的话,或发现第一种写法要快上一倍
尽量使用定义好的 url_path,也可以用 as 来自己定义名字
get '/books' => 'books#index', as: 'books'
比如 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.rb 太大的时候,我们可能会想要分离为多个文件来方便管理
# 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
config/routes/
├── admin.rb
└── user.rb
# config/routes/user.rb
resources :books
# config/routes/admin.rb
resources :authors