Spec-Zone.ru › Ruby on Rails 4.2

модуль ActionDispatch::Routing::Mapper::Scoping

Возможно, вам захочется организовать группы контроллеров в пространстве имён. Чаще всего, вы можете сгруппировать несколько административных контроллеров под пространством имён 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

Публичные методы экземпляра

constraints(constraints = {}) { || ... } Показать исходный код
# File actionpack/lib/action_dispatch/routing/mapper.rb, line 941
def constraints(constraints = {})
  scope(:constraints => constraints) { yield }
end

Ограничение параметра

Позволяет ограничить вложенные маршруты на основе набора правил. Например, чтобы изменить маршруты, чтобы разрешить использование точки в параметре 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(lambda { |req| req.env["HTTP_USER_AGENT"] =~ /iPhone/ }) do
  resources :iphones
end

Вы можете перенести эту логику в класс, если она слишком сложна для маршрутов. Этот класс должен иметь определенный метод matches?, который возвращает true, если пользователю должен быть предоставлен доступ к этому маршруту, или false, если пользователю доступ запрещен.

class Iphone
  def self.matches?(request)
    request.env["HTTP_USER_AGENT"] =~ /iPhone/
  end
end

Ожидаемое местоположение этого кода — lib/constraints.

Этот класс используется следующим образом:

constraints(Iphone) do
  resources :iphones
end
controller(controller, options={}) { || ... } Показать исходный код
# File actionpack/lib/action_dispatch/routing/mapper.rb, line 829
def controller(controller, options={})
  options[:controller] = controller
  scope(options) { yield }
end

Ограничивает маршруты определённым контроллером

controller "food" do
  match "bacon", action: "bacon"
end
defaults(defaults = {}) { || ... } Показать исходный код
# File actionpack/lib/action_dispatch/routing/mapper.rb, line 950
def defaults(defaults = {})
  scope(:defaults => defaults) { yield }
end

Позволяет установить параметры по умолчанию для маршрута, например так:

defaults id: 'home' do
  match 'scoped_pages/(:id)', to: 'pages#show'
end

Используя это, параметр :id здесь будет по умолчанию равен 'home'.

namespace(path, options = {}) { || ... } Показать исходный код
# File actionpack/lib/action_dispatch/routing/mapper.rb, line 872
def namespace(path, options = {})
  path = path.to_s

  defaults = {
    module:         path,
    path:           options.fetch(:path, path),
    as:             options.fetch(:as, path),
    shallow_path:   options.fetch(:path, path),
    shallow_prefix: options.fetch(:as, path)
  }

  scope(defaults.merge!(options)) { yield }
end

Ограничивает маршруты определённым пространством имён. Например:

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 <tt>Sekret::PostsController</tt> rather than <tt>Admin::PostsController</tt>
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
scope(*args) { || ... } Показать исходный код
# File actionpack/lib/action_dispatch/routing/mapper.rb, line 781
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] ||= {}).reverse_merge!(defaults)
  else
    block, options[:constraints] = options[:constraints], {}
  end

  @scope.options.each do |option|
    if option == :blocks
      value = block
    elsif option == :options
      value = options
    else
      value = options.delete(option)
    end

    if value
      scope[option] = send("merge_#{option}_scope", @scope[option], value)
    end
  end

  @scope = @scope.new scope
  yield
  self
ensure
  @scope = @scope.parent
end

Ограничивает набор маршрутов заданными параметрами по умолчанию.

Рассмотрим следующее определение маршрута:

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 <tt>Admin::PostsController</tt>
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

© 2004–2018 David Heinemeier Hansson
Licensed under the MIT License.

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API