Правильная маршрутизация для короткого URL-адреса по имени пользователя в Rails

Я пытаюсь заменить представления профиля пользователя такого рода

/users/1

с участием

/username

Я знаю, что это означает, что мне нужно проверить столкновения различных видов. Я проконсультировался со следующими подобными вопросами SO:

Вот различные неудачные определения маршрутов route.rb, которые я пробовал, и связанные с ними ошибки:

  1. 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'
    

    Вот мой соответствующий user_controller:

    6 def show
    7   @user = User.find(params[:id])
    8 end
    
  2. match "/:username" => 'users#show', :as => :profile

    Та же ошибка, что и выше.

  3. match "/:username", :controller => "users/:id", :action => 'show'

     Routing Error
    
     uninitialized constant Users
    
     Try running rake routes for more information on available routes.
    
  4. match '/:username', :controller => 'users', :action => 'show'

    Та же ошибка, что и 1.

  5. match '/:username', to: 'users/:id', via: 'show'

    Сервер не запускается.

  6. 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 ('/'[email protected])
        #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 не позаботится об этом.


person Mittenchops    schedule 17.07.2012    source источник


Ответы (2)


Первый правильный, но не работает, потому что вы все еще пытаетесь сделать что-то подобное внутри своего контроллера:

User.find(params[:username])

Когда вы должны вместо этого делать это:

User.find_by_username!(params[:username])

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

person Ryan Bigg    schedule 17.07.2012
comment
Я понимаю. Можете ли вы объяснить мне, что не так с текущим стилем контроллера? Как мне правильно думать о другом? - person Mittenchops; 17.07.2012
comment
Райан, вы очень подробно ответили на мой вопрос, но могу я спросить, как назвать маршрут перенаправления? Я пытаюсь это, но это не работает, в моем методе создания пользователя: @user = User.new(params[:user]) if @user.save redirect_to @user.username - person Mittenchops; 17.07.2012
comment
Неважно --- для тех, кто делает это, я решил это с помощью `redirect_to '/' + @user.username` - person Mittenchops; 17.07.2012
comment
@Mittenchops: Это довольно уродливо. Что бы я сделал, так это переопределил to_param в пользовательской модели, чтобы он возвращал только username, а затем только redirect_to @user перенаправлял на правильный путь. - person Ryan Bigg; 18.07.2012
comment
Я обновил, чтобы следить за вашим комментарием здесь --- можете ли вы указать мне, почему это не работает? redirect_to @user пытается перенаправить на ноль. - person Mittenchops; 21.07.2012
comment
@Mittenchops: это будет перенаправление на ноль, только если вы еще не установили @user или намеренно установили его на nil. - person Ryan Bigg; 24.07.2012

В дополнение к обновлению to_params внизу файла маршрутов нужна следующая строка:

resources :users, :path => '/'

person Mittenchops    schedule 21.07.2012