您可能希望将一组控制器组织在命名空间下。最常见的是,您可能将一些管理控制器分组到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"
在所有这些情况下,命名路由与您没有使用scope时保持一致。在最后一种情况下,以下路径映射到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
实例公共方法
constraints(constraints = {}, &block) 链接
参数限制
允许您根据一组规则来限制嵌套路由。例如,为了更改路由以允许在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(controller) 链接
将路由限定为特定控制器
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(defaults = {}) 链接
允许您为路由设置默认参数,例如
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
这将生成类似于resources
所生成的account_projects_path
之类的辅助方法。这里唯一的区别是生成的路由类似于/: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