Как определить RESTful маршруты в Rails для ресурса, который имеет несколько ключевых полей? - PullRequest
4 голосов
/ 03 марта 2009

Модель My User имеет обычный первичный ключ id, но также имеет уникальный login, который можно использовать в качестве идентификатора. Поэтому я хотел бы определить маршруты, чтобы пользователи могли получить доступ либо по id, либо по логину. В идеале маршруты должны быть примерно такими:

/users/:id (GET) => show (:id)
/users/:id (PUT) => update (:id)
...

/users/login/:login (GET) => show (:login)
/users/login/:login (PUT) => update (:login)
...

Каков наилучший способ сделать это (или что-то подобное)?

Ответы [ 4 ]

1 голос
/ 03 марта 2009

На самом деле у Кайла Буна правильная идея. Но это немного не так. Когда входит переменная params, все значения сохраняются как строки, поэтому его пример будет возвращать false каждый раз. Что вы можете сделать, это:

if params[:id].to_i.zero?
@user = User.find_by_login params[:id]
else
@user = User.find params[:id]
end

Таким образом, если: id является действительной строкой, Ruby просто конвертирует ее в 0. Вы можете проверить это, просмотрев хэш params с помощью гема ruby-debug.

(Я бы только что прокомментировал, но у меня пока недостаточно опыта;)

1 голос
/ 03 марта 2009

Пока лучшее, что я мог придумать, это:

map.resources :users

map.resources :users_by_login,
     :controller => "User",
     :only => [:show, :edit, :update, :destroy],
     :requirements => {:by_login => true}

Обычные маршруты RESTful создаются для пользователей, и, кроме того, ресурс users_by_login добавляет следующие маршруты (и только те):

GET    /users_by_login/:id/edit
GET    /users_by_login/:id/edit.:format
GET    /users_by_login/:id
GET    /users_by_login/:id.:format
PUT    /users_by_login/:id
PUT    /users_by_login/:id.:format
DELETE /users_by_login/:id
DELETE /users_by_login/:id.:format

Эти маршруты фактически также отображаются на UserController (только для методов show / edit / update / destroy). Добавлен дополнительный параметр by_login (равен true): таким образом, методы UserController могут определить, представляет ли параметр id логин или идентификатор.

Это делает работу, но я бы хотел, чтобы был лучший способ.

1 голос
/ 03 марта 2009

Просто проверьте, является ли идентификатор, переданный методам контроллера, целым числом.

if params[:id].is_a?(Integer)
    @user = User.find params[:id]
else
    @user = User.find_by_login params[:id]

Не нужно добавлять специальные маршруты.

0 голосов
/ 03 марта 2009

Не совсем уверен, что вы здесь делаете, но это может вам помочь.

Вы можете определить действия за пределами автоматических маршрутов RESTful, предоставляемых rails, добавив параметр : member или: collection .

map.resources :users, :member => { :login => [:post, :get] }

Это создаст маршруты, которые выглядят так:

/users/:id (GET)
...
/users/:id/login (GET)
/users/:id/login (POST)

Еще одна вещь, которую вы можете сделать, просто использовать логин в качестве атрибута, который вы ищите (при условии, что он уникален). Проверьте Райан Бейтс скринкаст на нем. В вашем контроллере у вас будет:

def show
@user = User.find_by_login(params[:id])
...
end

У него также есть еще одна заставка , которая может вам помочь. Второй рассказывает о нестандартных маршрутах.

...