跳到內容 跳到搜尋

您可能希望將控制器群組組織在一個命名空間下。最常見的情況下,您可能將多個管理控制器群組在 admin 命名空間下。您會將這些控制器放置在 app/controllers/admin 目錄下,並且可以在路由器中將它們分組在一起

namespace "admin" do
  resources :posts, :comments
end

這將為每個貼文和留言控制器建立多個路由。對於 Admin::PostsControllerRails 會建立

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
方法
C
D
N
S

實例公用方法

約束(約束 = {},&區塊)

參數限制

允許您根據一組規則限制嵌套路由。例如,為了更改路由以允許 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
# 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
# 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」。

# 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
# 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#matchResources#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
# 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