简体   繁体   中英

Rails custom route for user profile

I want to have the URL of a users profile in this format: mydomain.com/username

I have started to implement it in the user model:

user.rb

before_create :create_permalink
.
.
def to_param
  permalink
end
.
.
private

  def create_permalink
    self.permalink = username.downcase
  end

users_controller.rb

def show
  @user = User.find_by_permalink(params[:permalink])
end

routes.rb

match "/:permalink", to: "users#show", via: 'get'

When I visit mydomain.com/username a user profile does display but when I do it through the user_path(current_user) link, I get this error

undefined method `username' for nil:NilClass

and the URL is mydomain.com/user/username, which I don't want.

How do I edit the default rails route and edit user route to be in the format I want?

routes.rb:

Code::Application.routes.draw do
  resources :users,  except: [:edit, :show]
  resources :sessions, only: [:new, :create, :destroy]

  root 'pages#home'

  match '/help',    to: 'pages#help',    via: 'get'
  match '/about',   to: 'pages#about',   via: 'get'
  match '/contact', to: 'pages#contact', via: 'get'

  match '/signup',          to: 'users#new',        via: 'get'
  match '/signin',          to: 'sessions#new',     via: 'get'
  match '/signout',         to: 'sessions#destroy', via: 'delete'

  get '/:permalink',      to: 'users#show', as: 'user'
  get '/:permalink/edit', to: 'users#edit', as: 'edit_user'
end

After removing just the as: 'user' line and left as: 'edit_user' I ran bundle exec rake routes | grep -i "user" bundle exec rake routes | grep -i "user" :

    users GET    /users(.:format)           users#index
          POST   /users(.:format)           users#create
 new_user GET    /users/new(.:format)       users#new
     user PATCH  /users/:id(.:format)       users#update
          PUT    /users/:id(.:format)       users#update
          DELETE /users/:id(.:format)       users#destroy
   signup GET    /signup(.:format)          users#new
          GET    /:permalink(.:format)      users#show
edit_user GET    /:permalink/edit(.:format) users#edit

Don't use helper methods, give names to the routes:

get '/:permalink',      to: 'users#show', as: 'user'
get '/:permalink/edit', to: 'users#edit', as: 'edit_user'

it's cleaner, you also all the advantages of named routes

EDIT: your resource is creating a "user" named route for the update action

user PATCH  /users/:id(.:format)       users#update

You have two options to fix it:

1- The easiest (i would recomend this): use another name for those two new routes:

get '/:permalink',      to: 'users#show', as: 'custom_user'
get '/:permalink/edit', to: 'users#edit', as: 'custom_edit_user'

now you call those actions as "custom_user_path" and "custom_edit_user_path", no conflict

2- The more complicated: user another name for the resource

resource :users, except: [:edit, :show], as: 'old_users'
...
...
get '/:permalink',      to: 'users#show', as: 'user'
get '/:permalink/edit', to: 'users#edit', as: 'edit_user'

This way you can use user_path and edit_user_path but all the other "user*" routes will have to change to "old_user*_path", like: instead of "new_user_path" you would have to use "new_old_user_path".

I recommend you to use the 1st options, check all your code and use "custom_user_path" or "custom_edit_user_path" and you will be done

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM