2010-05-14 2 views
40

Использование Ruby On Rails 3 в новую систему маршрутизации, можно изменить значение по умолчанию: параметр IDИзменение параметра ID в Rails маршрутизации

resources :users, :key => :username 

выйти со следующими маршрутами

/users/new 
/users/:username 
/users/:username/edit 
...etc 

I я спрашиваю, потому что, хотя приведенный выше пример прост, было бы очень полезно сделать в текущем проекте, над которым я работаю.

Можно ли изменить этот параметр, а если нет, есть ли какая-то особая причина, почему бы и нет?

+3

Мне нравится этот вопрос с точки зрения «Как изменить идентификатор по умолчанию, используемый для извлечения пользователя/объекта/и т. Д.?» Тем не менее, я просто хочу включить плагин для скрытия этого идентификатора по умолчанию, поскольку он обычно является основным ключом непосредственно из базы данных, и есть всевозможные соображения безопасности, почему вы не должны раскрывать это значение (ослабление атак SQL-инъекций, допустимых идентификаторов для других пользователей, ...). В частности, использование имени пользователя позволяет напрямую атаковать учетную запись (pwd guessing). Использование большого случайного и уникального значения делает все это намного сложнее. Приветствия. –

+0

* Обязательно прочитайте ответы после принятого * – blnc

ответ

34

Если я вас правильно понимаю, то вы хотите, чтобы username вместо id в вашем url, не так ли?

Вы можете сделать это, переопределив метод to_param в вашей модели. Вы можете получить дополнительную информацию here.

+0

Я думаю, что это единственный способ сделать это пока. Кажется, это круговая обмотка. – joeellis

+1

Спасибо за этот указатель, полностью решил мою проблему. Я пришел сюда, чтобы узнать, как изменить этот b/c, по правилам, мы рассматриваем выборку из первичного ключа из сети в качестве проблемы безопасности. Вместо этого мы добавляем к объекту большое случайное и уникальное значение (SecureRandom.urlsafe_base64 (15)) и используем его как идентификатор, возвращаемый из to_param, и когда API RESTful find_by_OID. Возможно, когда я лучше понимаю рубин/рельсы, это можно превратить в драгоценный камень. –

0

Передайте имя пользователя в качестве входных данных для помощников путей.

В коде вида:

user_path(u.username) #/users/john 

В контроллере лечить id получил в username:

def show 
    user = User.find_by_username!(params[:id]) 
    ... 
end 
+0

Это то, что я делал, но я просто думаю, что было бы проще сделать что-то вроде User.find_by_username (params [: username]) в коде. Мне действительно интересно, почему Rails этого не позволяет. Возможно, это против какого-то принципа REST? – joeellis

1

Хотя ответ был принят спрашивающего, но есть простой подход к сделай это. Напишите этот код в своем контроллере.

authorize_resource :find_by => :username 

и на ваш взгляд, где вы хотите показать ссылку, напишите этот код.

<%= link_to "Username", user_path(u.username) %> 

Вам не нужны никакие другие изменения в ваших маршрутах или контроллере.

ОБНОВЛЕНИЕ: Это будет работать, только если вы используете драгоценный камень CanCan.

+0

Это метод CanCan. Его вообще не упоминается в rails api. [apidock.com] (http://apidock.com/rails/search?query=authorize_resource) [api.rubyonrails.org] (http://api.rubyonrails.org/?q=authorize_resource) – Nultyi

+0

Да, это метод CanCan. Я забыл упомянуть об этом в своем ответе. Я обновил ответ. – KULKING

1

Драгоценный камень FriendlyId может помочь вам в этом. У Райана Бейтса есть хороший video tutorial, используя этот драгоценный камень.

61

В маршруте Вы можете использовать

resources :user, param: :username 
+4

Это должен быть принятый ответ, мне гораздо удобнее добавлять аргумент в маршрут, чем переписывать метод 'to_param' – omnikron

+1

@omnikron. Это зависит от того, что вы пытаетесь достичь в своем приложении, иногда вам нужно делать как (например, когда вы хотите напрямую передать свой ресурс для маршрутизации помощников 'user_path @ user', так что вам не нужно делать' user_path @ user.username') ... но да, вы правы, это изящно, когда вы просто хотите функционировать маршрутизацию. – equivalent8

+3

Это работает только на Rails 4+ –

23

Для Ruby On Rails 4.1.4 (и, возможно более ранние версии), вы должны делать то, что какj.. и Ujjwal предложил:

1) В config/routes.rb добавить:

resources :user, param: :username 

2) В app/models/user.rb добавить:

def to_param 
    username 
end 

В вас только 1, тогда все ваши маршруты будут верными, как видно из rake routes:

$ rake routes 
    Prefix Verb URI Pattern     Controller#Action 
user_index GET /user(.:format)    user#index 
      POST /user(.:format)    user#create 
    new_user GET /user/new(.:format)   user#new 
edit_user GET /user/:username/edit(.:format) user#edit 
     user GET /user/:username(.:format)  user#show 
      PATCH /user/:username(.:format)  user#update 
      PUT /user/:username(.:format)  user#update 
      DELETE /user/:username(.:format)  user#destroy 

Однако вспомогательные методы, которые строят URL-адрес на основе экземпляра User, по-прежнему будут содержать id в URL-адресе, например. /user/1. Чтобы получить username в построенных URL-адресах, вам необходимо переопределить to_param, как в # 2.

+4

2) в большинстве случаев пропущен, когда возникает этот вопрос; это должен быть принятый ответ – Ben

+0

** работает с ** 'рельсами 5.0.2' ** и **' ruby ​​2.4.1' – blnc

Смежные вопросы