#ruby-on-rails #ruby #routes #nested-routes
#ruby-on-rails #ruby #маршруты #вложенные маршруты
Вопрос:
Я пытаюсь выяснить, как вложить маршруты в Rails 5 (чтобы связанные контроллеры хранились вместе.
У меня есть дерево файлов моих контроллеров, настроенное как:
app/controllers/users
В этой папке у меня есть контроллеры для:
identities_controller.rb
app_roles_controller.rb
Каждый из этих контроллеров сохраняется как:
class Users::IdentitiesController < ApplicationController
class Users::AppRolesController < ApplicationController
Мой файл маршрутов имеет:
resources :app_roles,
:controllers => {
:app_roles => 'users/app_roles'
}
devise_for :users,
:controllers => {
:sessions => 'users/sessions',
:registrations => "users/registrations",
:omniauth_callbacks => 'users/omniauth_callbacks'
}
resources :identities,
:controllers => {
:identities => 'users/identities'
}
resources :users
В моей папке views все файлы имеют верхний уровень. Мне неясно, нужно ли мне группировать их так же, как я делаю свои контроллеры.
Когда я сохраняю все это и пытаюсь перейти к http://localhost:3000/app_roles#index , я ожидаю перейти к моему приложению/views/app_roles/index.
Вместо этого я получаю сообщение об ошибке, в котором говорится:
app_roles
uninitialized constant AppRolesController
Когда я просматриваю маршруты, я получаю:
rake routes | grep app_roles
app_roles GET /app_roles(.:format) app_roles#index {:controllers=>{:app_roles=>"users/app_roles"}}
POST /app_roles(.:format) app_roles#create {:controllers=>{:app_roles=>"users/app_roles"}}
new_app_role GET /app_roles/new(.:format) app_roles#new {:controllers=>{:app_roles=>"users/app_roles"}}
edit_app_role GET /app_roles/:id/edit(.:format) app_roles#edit {:controllers=>{:app_roles=>"users/app_roles"}}
app_role GET /app_roles/:id(.:format) app_roles#show {:controllers=>{:app_roles=>"users/app_roles"}}
PATCH /app_roles/:id(.:format) app_roles#update {:controllers=>{:app_roles=>"users/app_roles"}}
PUT /app_roles/:id(.:format) app_roles#update {:controllers=>{:app_roles=>"users/app_roles"}}
DELETE /app_roles/:id(.:format) app_roles#destroy {:controllers=>{:app_roles=>"users/app_roles"}}
Для меня, я думаю, эти маршруты показывают, что app_roles#index должен перейти в app/views/app_roles/index.html.erb через контроллер в app/controllers/users/app_roles_controller.rb
У меня такая же проблема с ресурсом identities.
ПРЕДПОЛАГАЮ, что я попытался переместить папку app / views / app_roles, которая будет вложена в папку users (т. Е. app / views / users), но я получаю ту же ошибку, когда затем пытаюсь перейти к http://localhost:3000/app_roles#index чтобы проверить, работает ли это.
Я также попытался изменить файл маршрутов на:
resources :app_roles,
:resources => {
:app_roles => 'users/app_roles'
}
Под этим я подразумеваю, что я изменил ссылку на :controllers на :resources . Это не сработало — я получаю ту же ошибку.
Кто-нибудь может увидеть, что я делаю не так?
Комментарии:
1. возможно, попробуйте поместить ваши файлы в папку с пространством имен, т.Е.
app/controllers/users/<my_controller>.rb
.2. они находятся в: app / controllers / users
3. у вас тоже есть a
app/controllers/user_controller
? Он может просто содержатьclass UsersController < ApplicationController; end
4. Я делаю — мой UsersController имеет верхний уровень (не вложен в папку app / controllers / users)
Ответ №1:
Маршрутизация на контроллеры с пространством имен
Чтобы перенаправить ресурсы на контроллер с «пространством имен», вы можете использовать module
опцию:
resources :identities, module: :users
Или scope module:
что полезно при объявлении нескольких ресурсов:
scope module: :users do
resources :app_roles, module: :users
resources :identities, module: :users
end
Это намного чище, чем указывать контроллер вручную, что на самом деле делается только тогда, когда вы переопределяете библиотеку, такую как Devise, или когда имена контроллера и маршрута не совпадают.
Терминология здесь может быть несколько запутанной. Просто помните, что единственное, что делает маршрут, — это сопоставляет входящий запрос с контроллером. Это не влияет на то, как контроллер выполняет свою работу.
Просмотр просмотров
Для меня, я думаю, эти маршруты показывают, что app_roles#index должен перейти в app/views/app_roles/index.html.erb через контроллер в app/controllers/users/app_roles_controller.rb
Ну, это не так, как это работает.Rails просматривает представления на основе вложенности класса контроллера. Таким образом, rails будет искать представления для Users::IdentitiesController
in views/users/indentities/
.
Если вы хотите нарушить соглашения, вы можете явно отображать представления или добавлять / добавлять пути просмотра. Однако изучите соглашения, прежде чем нарушать их, они на самом деле довольно умные.
Обратите внимание, что ваши маршруты не влияют на то, как ваши контроллеры просматривают просмотры. Это зависит только от вложенности модуля — то есть от того, как составлен объект. И не имеет абсолютно ничего общего с концепцией вложенных маршрутов.
«пространства имен» и вложенные маршруты
Создаваемые вами маршруты не являются вложенными. Вложенный маршрут будет, например:
POST /users/:user_id/identities
Что четко описывает намерение. Чтобы настроить вложенные маршруты для indentities
вас, выполните:
resources :users, shallow: true do
scope module: :users do
resources :identities
end
end
shallow: true
генерирует отдельные маршруты без users/:used_id/
префикса.
Prefix Verb URI Pattern Controller#Action
user_identities GET /users/:user_id/identities(.:format) users/identities#index
POST /users/:user_id/identities(.:format) users/identities#create
new_user_identity GET /users/:user_id/identities/new(.:format) users/identities#new
edit_identity GET /identities/:id/edit(.:format) users/identities#edit
identity GET /identities/:id(.:format) users/identities#show
PATCH /identities/:id(.:format) users/identities#update
PUT /identities/:id(.:format) users/identities#update
DELETE /identities/:id(.:format) users/identities#destroy
users GET /users(.:format) users#index
POST /users(.:format) users#create
new_user GET /users/new(.:format) users#new
edit_user GET /users/:id/edit(.:format) users#edit
user GET /users/:id(.:format) users#show
PATCH /users/:id(.:format) users#update
PUT /users/:id(.:format) users#update
DELETE /users/:id(.:format) users#destroy
Комментарии:
1. Привет, Макс, большое спасибо за объяснение. Когда я выполняю неглубокую вложенность, означает ли это, что я должен хранить свою папку представлений identities, вложенную в папку представлений пользователей? Я хочу сделать это для аккуратности в моей файловой структуре, но я интуитивно не понимаю, что отключает мелкий переключатель в файловой структуре представлений.
2. Маршруты не влияют на то, как контроллер просматривает представления. Они просто вызывают соответствующий контроллер #action
3. Просмотр просмотра определяется только тем, как объявлен класс контроллера. Если он заключен в модуль, то rails будет использовать этот модуль при поиске.
4. Хорошо, но когда вы говорите «завернутый в модуль», вы имеете в виду, что способ, которым я написал свои вложенные контроллеры, соответствует формату «wrap in module»? Начальная строка моих вложенных контроллеров: class Users::IdentitiesController <ApplicationController
5. Большое спасибо за пояснения. Я изо всех сил пытаюсь разобраться в жаргоне и не могу найти хорошие, простые переводы документов ruby на английский.