您可能希望將控制器群組組織在一個命名空間下。最常見的情況下,您可能將多個管理控制器群組在 admin
命名空間下。您會將這些控制器放置在 app/controllers/admin
目錄下,並且可以在路由器中將它們分組在一起
namespace "admin" do
resources :posts, :comments
end
這將為每個貼文和留言控制器建立多個路由。對於 Admin::PostsController
,Rails
會建立
GET /admin/posts
GET /admin/posts/new
POST /admin/posts
GET /admin/posts/1
GET /admin/posts/1/edit
PATCH/PUT /admin/posts/1
DELETE /admin/posts/1
如果你想將 /posts(不帶前綴 /admin)路由到 Admin::PostsController
,你可以使用
scope module: "admin" do
resources :posts
end
或者,對於單一情況來說
resources :posts, module: "admin"
如果你想將 /admin/posts 路由到 PostsController
(沒有 Admin::
模組前綴),你可以使用
scope "/admin" do
resources :posts
end
或者,對於單一情況來說
resources :posts, path: "/admin/posts"
在這些情況中,命名路由與您不使用範圍的情況下相同。在最後一種情況下,下列路徑會對應到 PostsController
GET /admin/posts
GET /admin/posts/new
POST /admin/posts
GET /admin/posts/1
GET /admin/posts/1/edit
PATCH/PUT /admin/posts/1
DELETE /admin/posts/1
實例公用方法
約束(約束 = {},&區塊) 連結
參數限制
允許您根據一組規則限制嵌套路由。例如,為了更改路由以允許 id
參數中出現點字元
constraints(id: /\d+\.\d+/) do
resources :posts
end
現在,諸如 /posts/1
的路由將不再有效,但是 /posts/1.1
會有效。對於此範例,id
參數必須符合傳入的限制。
您也可以使用這項功能來限制其他參數
resources :posts do
constraints(post_id: /\d+\.\d+/) do
resources :comments
end
end
根據 IP 限制
路由也可以限制在一個 IP 或特定範圍的 IP 位址
constraints(ip: /192\.168\.\d+\.\d+/) do
resources :posts
end
任何從 192.168.* 範圍連線的使用者都可以看到此資源,而從此範圍以外連線的任何使用者將會收到不存在此路由的通知。
動態請求比對
可以根據特定條件限制路由的請求
constraints(-> (req) { /iPhone/.match?(req.env["HTTP_USER_AGENT"]) }) do
resources :iphones
end
如果您發現對路由來說過於複雜,您可以將這個邏輯移出到一個類別中。此類別必須定義一個 matches?
方法,如果使用者應該可以存取該路由,則此方法會傳回 true
,否則會傳回 false
。
class Iphone
def self.matches?(request)
/iPhone/.match?(request.env["HTTP_USER_AGENT"])
end
end
程式碼的預期放置位置為 lib/constraints
。
此類別的使用方式如下
constraints(Iphone) do
resources :iphones
end
來源: 顯示 | 在 GitHub 上
# File actionpack/lib/action_dispatch/routing/mapper.rb, line 1034 def constraints(constraints = {}, &block) scope(constraints: constraints, &block) end
控制器(控制器) 連結
將路由限定到特定的控制器
controller "food" do
match "bacon", action: :bacon, via: :get
end
來源: 顯示 | 在 GitHub 上
# File actionpack/lib/action_dispatch/routing/mapper.rb, line 916 def controller(controller) @scope = @scope.new(controller: controller) yield ensure @scope = @scope.parent end
預設值(預設值 = {}) 連結
允許您設定路由的預設參數,例如這個
defaults id: 'home' do
match 'scoped_pages/(:id)', to: 'pages#show'
end
利用這點,這邊的 :id
參數預設值為「home」。
資料來源:顯示 | 在 GitHub 上
# File actionpack/lib/action_dispatch/routing/mapper.rb, line 1045 def defaults(defaults = {}) @scope = @scope.new(defaults: merge_defaults_scope(@scope[:defaults], defaults)) yield ensure @scope = @scope.parent end
namespace(path, options = {}, &block) 連結
將路由限定到特定名稱空間。例如
namespace :admin do
resources :posts
end
這會產生下列路由
admin_posts GET /admin/posts(.:format) admin/posts#index
admin_posts POST /admin/posts(.:format) admin/posts#create
new_admin_post GET /admin/posts/new(.:format) admin/posts#new
edit_admin_post GET /admin/posts/:id/edit(.:format) admin/posts#edit
admin_post GET /admin/posts/:id(.:format) admin/posts#show
admin_post PATCH/PUT /admin/posts/:id(.:format) admin/posts#update
admin_post DELETE /admin/posts/:id(.:format) admin/posts#destroy
選項
:path
、:as
、:module
、:shallow_path
和 :shallow_prefix
選項全部預設為名稱空間的名稱。
有關選項,請參閱 Base#match
。有關 :shallow_path
選項,請參閱 Resources#resources
。
# accessible through /sekret/posts rather than /admin/posts
namespace :admin, path: "sekret" do
resources :posts
end
# maps to +Sekret::PostsController+ rather than +Admin::PostsController+
namespace :admin, module: "sekret" do
resources :posts
end
# generates +sekret_posts_path+ rather than +admin_posts_path+
namespace :admin, as: "sekret" do
resources :posts
end
資料來源:顯示 | 在 GitHub 上
# File actionpack/lib/action_dispatch/routing/mapper.rb, line 961 def namespace(path, options = {}, &block) path = path.to_s defaults = { module: path, as: options.fetch(:as, path), shallow_path: options.fetch(:path, path), shallow_prefix: options.fetch(:as, path) } path_scope(options.delete(:path) { path }) do scope(defaults.merge!(options), &block) end end
scope(*args) 連結
將一組路由限定到指定的預設選項。
以下將路線定義列為範例
scope path: ":account_id", as: "account" do
resources :projects
end
它會產生像 account_projects_path
之類的輔助程式,就像 resources
所做的。此處的不同之處在於產生的路由類似於 /:account_id/projects,而不是 /accounts/:account_id/projects。
選項
與 Base#match
和 Resources#resources
使用相同的選項。
# route /posts (without the prefix /admin) to +Admin::PostsController+
scope module: "admin" do
resources :posts
end
# prefix the posts resource's requests with '/admin'
scope path: "/admin" do
resources :posts
end
# prefix the routing helper name: +sekret_posts_path+ instead of +posts_path+
scope as: "sekret" do
resources :posts
end
資料來源:顯示 | 在 GitHub 上
# File actionpack/lib/action_dispatch/routing/mapper.rb, line 857 def scope(*args) options = args.extract_options!.dup scope = {} options[:path] = args.flatten.join("/") if args.any? options[:constraints] ||= {} unless nested_scope? options[:shallow_path] ||= options[:path] if options.key?(:path) options[:shallow_prefix] ||= options[:as] if options.key?(:as) end if options[:constraints].is_a?(Hash) defaults = options[:constraints].select do |k, v| URL_OPTIONS.include?(k) && (v.is_a?(String) || v.is_a?(Integer)) end options[:defaults] = defaults.merge(options[:defaults] || {}) else block, options[:constraints] = options[:constraints], {} end if options.key?(:only) || options.key?(:except) scope[:action_options] = { only: options.delete(:only), except: options.delete(:except) } end if options.key? :anchor raise ArgumentError, "anchor is ignored unless passed to `match`" end @scope.options.each do |option| if option == :blocks value = block elsif option == :options value = options else value = options.delete(option) { POISON } end unless POISON == value scope[option] = send("merge_#{option}_scope", @scope[option], value) end end @scope = @scope.new scope yield self ensure @scope = @scope.parent end