Правильная маршрутизация для короткого URL по имени пользователя в Rails
Я пытаюсь заменить вид профиля пользователя такого рода
/users/1
с
/username
Я знаю, что это означает, что мне нужно будет проверять наличие столкновений разных типов. Я консультировался со следующими подобными вопросами SO:
- Ruby on rails
- настроить рельсы URL с именем пользователя
- Маршрутизация в Rails делает имя пользователя URL-адресом:
- ошибка маршрутизации с: имя пользователя в URL
Вот различные неудачные определения маршрутов route.rb, которые я пробовал, и связанные с ними ошибки:
match "/:username" => "users#show", via: "get"
Вот ошибка:
ActiveRecord::RecordNotFound in UsersController#show Couldn't find User without an ID app/controllers/users_controller.rb:7:in `show'
Вот мой соответствующий users_controller:
6 def show 7 @user = User.find(params[:id]) 8 end
match "/:username" => 'users#show', :as => :profile
Та же ошибка, что и выше.
match "/:username", :controller => "users/:id", :action => 'show'
Routing Error uninitialized constant Users Try running rake routes for more information on available routes.
match '/:username', :controller => 'users', :action => 'show'
Та же ошибка, что и 1.
match '/:username', to: 'users/:id', via: 'show'
Сервер не запускается.
match "/:username" => redirect("/users/:id")
Ошибка:
ActiveRecord::RecordNotFound in UsersController#show Couldn't find User with id=:id
Любая идея, почему моя маршрутизация не работает так же, как все остальные, кто задает этот вопрос?
Обновить
Просто чтобы убрать эту проблему из комментариев и поставить ее в вопросе более четко. После внесения изменений @Ryan Bigg ниже, у меня возникла проблема с маршрутизацией при перенаправлении в профиль при создании нового. Вот мой код создания:
def create
@user = User.new(params[:user])
if @user.save
session[:user_id] = @user.id
flash[:success] = "Thank you for signing up."
redirect_to ('/'+@user.username)
#redirect_to @user, notice: "Thank you for signing up!"
else
render "new"
end
end
А вот и мой user.rb
def to_param
self.username
#username
end
Тем не менее, закомментированное перенаправление, которое, как мне кажется, должно работать с обновлением to_param, не работает, в то время как уродливый хакер, приведенный выше, работает. Почему перезапись to_param, которая работала для других людей, не работает в моем приложении? Мои методы #update и #edit также не работают, так как их перенаправления переходят в "users/1/edit" вместо "username/edit", если перезапись to_param не позаботится об этом.
2 ответа
Первый - правильный, но не работает, потому что вы все еще пытаетесь сделать что-то подобное в вашем контроллере:
User.find(params[:username])
Когда вы должны вместо этого делать это:
User.find_by_username!(params[:username])
Первый попытается найти по первичному ключу вашей таблицы, а второй вместо этого будет правильно запрашивать поле имени пользователя.
В дополнение к обновлению to_params, нижней части файла маршрутов нужна следующая строка:
resources :users, :path => '/'