Spec-Zone.ru › Ruby on Rails 8.1

модуль ActionDispatch::Routing

Модуль маршрутизации обеспечивает переписывание URL на чистом Ruby. Это способ перенаправлять входящие запросы к контроллерам и действиям. Он заменяет правила mod_rewrite. И самое главное — Routing Rails работает с любым веб-сервером. Маршруты определяются в config/routes.rb.

Представьте, что создание маршрутов — это составление карты для ваших запросов. Карта указывает им путь на основе заранее заданного шаблона:

Rails.application.routes.draw do
  Pattern 1 tells some request to go to one place
  Pattern 2 tell them to go to another
  ...
end

Следующие символы являются специальными:

:controller maps to your controller name
:action     maps to an action with your controllers

Другие имена просто сопоставляются с параметром, как в случае с :id.

Ресурсы

Маршрутизация ресурсов позволяет быстро объявить все распространённые маршруты для контроллера, работающего с ресурсами. Вместо объявления отдельных маршрутов для действий index, show, new, edit, create, update и destroy ресурсный маршрут объявляет их одной строкой кода:

resources :photos

Иногда у вас есть ресурс, к которому клиенты всегда обращаются без указания идентификатора. Распространённый пример: /profile всегда показывает профиль пользователя, который в данный момент вошёл в систему. В этом случае можно использовать единичный ресурс, чтобы сопоставить /profile (вместо /profile/:id) с действием show.

resource :profile

Часто ресурсы логически являются дочерними по отношению к другим ресурсам:

resources :magazines do
  resources :ads
end

Возможно, вы захотите объединить группы контроллеров в пространстве имён. Обычно несколько административных контроллеров можно объединить в пространстве имён admin. Эти контроллеры следует разместить в каталоге app/controllers/admin, а затем сгруппировать в маршрутизаторе:

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

В качестве альтернативы можно добавить префиксы к путям, не используя отдельный каталог, с помощью scope. scope принимает дополнительные параметры, которые применяются ко всем заключённым в него маршрутам.

scope path: "/cpanel", as: 'admin' do
  resources :posts, :comments
end

Дополнительные сведения см. в разделах Routing::Mapper::Resources#resources, Routing::Mapper::Scoping#namespace и Routing::Mapper::Scoping#scope.

Маршруты без ресурсов

Для маршрутов, которые не вписываются в модель resources, можно использовать вспомогательные методы HTTP get, post, patch, put и delete.

get 'post/:id', to: 'posts#show'
post 'post/:id', to: 'posts#create_comment'

Теперь, если отправить POST-запрос на /posts/:id, он будет направлен к действию create_comment. GET-запрос на тот же URL будет направлен к действию show.

Если маршрут должен обрабатывать несколько методов HTTP (или все методы), предпочтительнее использовать параметр :via для match.

match 'post/:id', to: 'posts#show', via: [:get, :post]

Именованные маршруты

Маршрутам можно присваивать имена с помощью параметра :as, чтобы удобно обращаться к ним в исходном коде: name_of_route_url для полного URL и name_of_route_path для пути URI.

Пример:

# In config/routes.rb
get '/login', to: 'accounts#login', as: 'login'

# With render, redirect_to, tests, etc.
redirect_to login_url

Можно также передавать аргументы.

redirect_to show_item_path(id: 25)

Используйте root как сокращённую запись для именования маршрута корневого пути «/».

# In config/routes.rb
root to: 'blogs#index'

# would recognize http://www.example.com/ as
params = { controller: 'blogs', action: 'index' }

# and provide these named routes
root_url   # => 'http://www.example.com/'
root_path  # => '/'

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

# In config/routes.rb
controller :blog do
  get 'blog/show'    => :list
  get 'blog/delete'  => :delete
  get 'blog/edit'    => :edit
end

# provides named routes for show, delete, and edit
link_to @article.title, blog_show_path(id: @article.id)

Человекопонятные URL

Маршруты могут генерировать человекопонятные URL. Например:

get '/articles/:year/:month/:day', to: 'articles#find_by_id', constraints: {
  year:       /\d{4}/,
  month:      /\d{1,2}/,
  day:        /\d{1,2}/
}

С указанным выше маршрутом URL «localhost:3000/articles/2005/11/06» сопоставляется с

params = {year: '2005', month: '11', day: '06'}

Регулярные выражения и параметры

Можно указать регулярное выражение, задающее формат параметра.

controller 'geocode' do
  get 'geocode/:postalcode', to: :show, constraints: {
    postalcode: /\d{5}(-\d{4})?/
  }
end

Ограничения могут включать модификаторы регулярных выражений «игнорировать регистр» и «расширенный синтаксис»:

controller 'geocode' do
  get 'geocode/:postalcode', to: :show, constraints: {
    postalcode: /hx\d\d\s\d[a-z]{2}/i
  }
end

controller 'geocode' do
  get 'geocode/:postalcode', to: :show, constraints: {
    postalcode: /# Postalcode format
       \d{5} #Prefix
       (-\d{4})? #Suffix
       /x
  }
end

Использование многострочного модификатора вызовет ArgumentError. Модификаторы регулярных выражений для кодировки молча игнорируются. Для сопоставления всегда используется кодировка по умолчанию или ASCII.

Внешние перенаправления

С помощью вспомогательного метода redirect в маршрутизаторе можно перенаправить любой путь на другой:

get "/stories", to: redirect("/posts")

Маршруты с символами Unicode

В маршрутизаторе можно задавать маршруты с символами Unicode:

get "こんにちは", to: "welcome#index"

Routing к приложениям Rack

Вместо String, например posts#index, который соответствует действию index в PostsController, в качестве конечной точки сопоставителя можно указать любое приложение Rack:

get "/application.js", to: Sprockets

Повторная загрузка маршрутов

При необходимости маршруты можно перезагрузить:

Rails.application.reload_routes!

Будут удалены все именованные маршруты, а config/routes.rb будет перезагружен, если файл изменился после последней загрузки. Чтобы принудительно выполнить перезагрузку, используйте reload!.

Тестирование маршрутов

Два основных метода для тестирования маршрутов:

assert_routing

def test_movie_route_properly_splits
  opts = {controller: "plugin", action: "checkout", id: "2"}
  assert_routing "plugin/checkout/2", opts
end

assert_routing позволяет проверить, корректно ли маршрут преобразуется в параметры.

assert_recognizes

def test_route_has_options
  opts = {controller: "plugin", action: "show", id: "12"}
  assert_recognizes opts, "/plugins/show/12"
end

Обратите внимание на тонкое различие между ними: assert_routing проверяет, соответствует ли URL параметрам, а assert_recognizes — корректно ли URL разбирается на параметры.

В тестах можно просто передать URL или именованный маршрут в get или post.

def send_to_jail
  get '/jail'
  assert_response :success
end

def goes_to_login
  get login_url
  #...
end

Просмотр списка всех маршрутов

$ bin/rails routes

Чтобы выбрать конкретный контроллер, используйте -c, а для поиска маршрутов — -g. Это удобно использовать вместе с --expanded, который отображает маршруты вертикально.

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

Spec-Zone.ru

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