модуль 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.