замените user_id на имя пользователя на странице показа в рельсах

Адские друзья

Я хочу показать имя пользователя вместо user_id на странице показа пользователя.

Например,

в базе данных существует usr_id 300 для пользователя с именем harry. Итак, как показать

http://localhost:3000/harry

вместо

http://localhost:3000/user/300

в URL.

Можно ли это сделать в файле маршрутов?

Спасибо


person Gagan    schedule 27.02.2011    source источник


Ответы (3)


Это обычно называют тщеславным URL-адресом, и с небольшой осторожностью вы можете справиться с этим довольно легко. Первый...

  1. Убедитесь, что это последняя вещь в ваших маршрутах. Вы не хотите, чтобы ваши имена пользователей переопределяли пространство имен другого контроллера.
  2. Используйте разумный список исключений, чтобы запретить пользователям использовать такие имена пользователей, как admin, support, Official, Secure и т. д.

В ваших маршрутах:

# the simple case
get '/:username' => 'users#show', :constrain => { :username => /[a-zA-Z-]+/ }

# ...with vanity_url_path(@user) helpers
get '/:username' => 'users#show', :as => 'vanity_url'

# or routing something more complicated with all the default resourceful routes
resources :users, :path => '/:username'

# or even just defining a bunch of routes for users with this format
controller :users, :path => '/:username' do
  get '/profile', :action => :profile    #=> /johnsmith/profile => UsersController#profile
end

В приведенном выше коде я избегал дублирования опции :constrain для каждого маршрута для ясности. Вы захотите настроить регулярное выражение в соответствии с вашими именами пользователей, а затем убедитесь, что оно у вас есть на любом маршруте, по которому вы идете.

Если это будет способ доступа к пользователям из вашего приложения по умолчанию (т. е. не просто удобный способ доступа к профилю пользователя), вы захотите переопределить метод to_param в своей модели Users. Это позволяет вам использовать помощники url_for, такие как form_for @user, без указания дополнительных аргументов.

class User
  def to_param
    username
  end
end

Еще один небольшой совет: если вы играете со своими маршрутами и пытаетесь сделать что-то большее, чем основы, не забудьте часто вызывать $ rake routes из командной строки, чтобы увидеть, какие маршруты в настоящее время распознает Rails. Очистить те, которые вам не нужны, тоже полезно. ;)

person coreyward    schedule 27.02.2011
comment
Кажется, он заменил id(300) на имя harry, но также выдал ошибку, говоря, что не найдена запись с id harry. Я вставил get '/: username' => 'users#show', :constrain =› { :username =› /[a-zA-Z-]+/ } в конец файла маршрута и добавлено to_params в мою модель пользователя. Я что-то упустил или сделал что-то не так? - person Gagan; 28.02.2011
comment
@Gagan Вам все еще нужно обновить методы вашего контроллера, чтобы найти пользователя по параметру имени пользователя. По умолчанию это что-то вроде User.find(params[:id]), которое ожидает числовые идентификаторы первичного ключа. Вместо этого вы хотите что-то вроде User.find_by_username(params[:username]). - person coreyward; 28.02.2011

Если вы хотите иметь /:username, попробуйте это в вашем файле route.rb (ЭТО ДОЛЖНО БЫТЬ ПОСЛЕДНЯЯ СТРОКА БЛОКА! - Создан последний маршрут!)

match "/:id", :to => "users#show", :as => :friendly_user

Затем, просто чтобы сделать это менее ужасным, вы можете использовать гем make_permalink, чтобы легко создавать понятные URL-имена и переопределить метод to_param в вашей модели

# models/user.rb
make_permalink :username    

def to_param
  permalink
end

А чтобы было еще лучше, переопределите метод User.find для работы по постоянной ссылке или по id

def self.find(query)
  self.find_by_username(query) || super(query)
end

Это будет работать для User.find(1) или User.find(my_username).

Надеюсь, это поможет,

Николас Хок Исаза

person Hock    schedule 27.02.2011

попробуйте что-то подобное в route.rb

map.user_permalink 'users/:user_name', :controller => 'users', :action => 'show'

позже в представлениях используйте это так:

<%= link_to user.name, user_permalink_path(user.user_name.parameterize) %>

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

person Milan Jaric    schedule 27.02.2011