Ответ 1
Маршруты ресурсов предназначены для работы таким образом. Если вы хотите что-то другое, спроектируйте его самостоятельно, как это.
match 'users/me' => 'users#me', :via => :get
Поместите его вне вашего блока resources :users
Я разрабатываю REST api на основе рельсов. Чтобы использовать этот api, вы ДОЛЖНЫ войти в систему. Что касается этого, я хотел бы создать метод me
в моем пользовательском контроллере, который вернет json из зарегистрированных данных пользователя.
Поэтому мне не нужно передавать :id
в URL-адрес. Я просто хочу назвать http://domain.com/api/users/me
Итак, я пробовал это:
namespace :api, defaults: { format: 'json' } do
scope module: :v1, constraints: ApiConstraints.new(version: 1, default: true) do
resources :tokens, :only => [:create, :destroy]
resources :users, :only => [:index, :update] do
# I tried this
match 'me', :via => :get
# => api_user_me GET /api/users/:user_id/me(.:format) api/v1/users#me {:format=>"json"}
# Then I tried this
member do
get 'me'
end
# => me_api_user GET /api/users/:id/me(.:format) api/v1/users#me {:format=>"json"}
end
end
end
Как вы можете видеть, мой маршрут ждет идентификатора, но я хотел бы получить что-то вроде devise. Что-то основано на current_user
id. Пример ниже:
edit_user_password GET /users/password/edit(.:format) devise/passwords#edit
В этом примере вы можете редактировать текущий пароль пользователя, не передавая id в качестве параметра.
Я мог бы использовать коллекцию вместо члена, но это грязный обход...
У кого-то есть идея? Спасибо вам
Маршруты ресурсов предназначены для работы таким образом. Если вы хотите что-то другое, спроектируйте его самостоятельно, как это.
match 'users/me' => 'users#me', :via => :get
Поместите его вне вашего блока resources :users
Путь к использованию уникальных ресурсов:
Итак, вместо resources
используйте resource
:
Иногда у вас есть ресурс, который клиенты всегда ищут без ссылки на ID. Например, вы хотите, чтобы /profile всегда показывал профиль текущего пользователя. В этом случае вы можете использовать особый ресурс для map/profile (а не /profile/: id) для действия show [...]
Итак, в вашем случае:
resource :user do
get :me, on: :member
end
# => me_api_user GET /api/users/me(.:format) api/v1/users#me {:format=>"json"}
Возможно, я что-то упустил, но почему бы вам не использовать:
get 'me', on: :collection
resources :users, only: [:index, :update] do
collection do
get :me, action: 'show'
end
end
указание действия не является обязательным. вы можете пропустить действие здесь и назовите действие своего контроллера как me
.
Вы можете использовать
resources :users, :only => [:index, :update] do
get :me, on: :collection
end
или
resources :users, :only => [:index, :update] do
collection do
get :me
end
end
"Маршруту участника требуется идентификатор, потому что он действует на члена. Маршрут коллекции не потому, что он действует на коллекцию объектов. Предварительный просмотр - пример маршрута участника, поскольку он действует (и отображает ) один объект. Поиск - пример маршрута коллекции, поскольку он действует (и отображает) коллекцию объектов". (от here)
Когда вы создаете маршрут, вложенный в ресурс, вы можете указать, является ли это действием члена или действием коллекции.
namespace :api, defaults: { format: 'json' } do
scope module: :v1, constraints: ApiConstraints.new(version: 1, default: true) do
resources :tokens, :only => [:create, :destroy]
resources :users, :only => [:index, :update] do
# I tried this
match 'me', :via => :get, :collection => true
...
...
Это дает тот же результат, что и Arjan более простым способом
get 'users/me', to: 'users#me'