user3648746
user3648746

Reputation: 13

Accessing current_user in Rails route

Please forgive me... I know there are other posts with a similar title but I have not seen my question so...

I am trying to create a url mysite.com/myusername/profile and I was wondering how to create the route for that. At the moment, the url for user#profile is just that, mysite.com/user/profile, but I want to make it something more specific like say each user has a username like JohnnySmith the URL would be mysite.com/JohnnySmith/profile. I was thinking something like

get "/#{current_user.username}", to: "user#profile", as: user_profile 

but I know this isn't correct.

I should mention that, too, that it is not possible for just anyone to access mysite.com/JohnnySmith/profile.... the current user would have to be JohnnySmith.

Can someone help? Thanks.

Upvotes: 1

Views: 1331

Answers (2)

Richard Peck
Richard Peck

Reputation: 76784

You need to use friendly_id with CanCanCan for authorization.


Essentially, what you're trying to do is allow Rails to process usernames through the params. This can be done without friendly_id, but is somewhat hacky.

Using the friendly_id gem will allow you to use the following:

#Gemfile
gem "friendly_id"

$ rails generate friendly_id
$ rails generate scaffold user name:string slug:string:uniq
$ rake db:migrate

#app/models/user.rb
class User < ActiveRecord::Base
   extend FriendlyID
   friendly_id :username, use: [:finders, :slugged]
end

You'd then be able to use:

#config/routes.rb
resources :users, path: "", only: [] do
   get :profile, action: :show, on: :member #-> url.com/:id/profile
end

#app/controllers/users_controller.rb
class UsersController < ApplicationController
   def show
      @user = User.find params[:id]
   end
end

This will automatically translate params[:id] into the slug attribute for the User model:

<%= link_to "Profile", user_profile_path(current_user) %>
# -> url.com/:current_user_name/profile

--

The next stage to this is authorization.

Using CanCanCan should make it so that only the current_user can view their profile:

#Gemfile
gem "cancancan"

#app/models/ability.rb
class Ability
  include CanCan::Ability

  def initialize(user)
    user ||= User.new # guest user (not logged in)
    can :read, User, id: user.id
  end
end

You can then use load_and_authorize_resource in your users controller:

#app/controllers/users_controller.rb
class UsersController < ApplicationController
   load_and_authorize_resource

   def show
   end
end

Upvotes: 0

Van Huy
Van Huy

Reputation: 1627

If you want to pass a parameter in a route, it should be

get "/:username/profile", to: "user#profile", as: user_profile

Please take a look at http://guides.rubyonrails.org/routing.html#naming-routes

Then you can use params[:username] in your controller to validate the user like

if current_user.username != params[:username]
   # redirect to error page

Or you can use cancancan gem to do this.

Upvotes: 1

Related Questions