aishaq11
aishaq11

Reputation: 179

Get UserID for Current User using Devise/Rails

So I, a rails newbie, am currently trying to get the User ID from the current Devise session, and I am having a bit of trouble.

I have this in my controller now:

def index
  @currentUser = current_user.id
end

And I want to make a simple if statement to show/hide fields in my form.

<% if @currentUser === @product.user_id %>
          <%= link_to "Back", products_path %>
          <%= link_to "Edit", edit_product_path(@product) %>
          <%= link_to "Delete", product_path(@product), method: :delete, data: { confirm: "Are you sure?"} %>
      <% else %>
          <span></span>
<% end %>

I have a feeling my syntax in defining my currentUser variable is bad, but I have no idea how to fix this. There were a few similar questions on Stack, but none of them really applied to me or helped me.

Thanks in advance!

Upvotes: 10

Views: 31422

Answers (5)

msdundar
msdundar

Reputation: 383

Comparing IDs is not the best practice for Rails. If you have previously set up the associations correctly, then you don't need to make a comparison between IDs. For example:

User
has_many :group_events

GroupEvent
belongs_to :user

In this scenario, instead of comparing IDs, you can directly compare with association:

Bad
@group_event.user_id == current_user.id

Good
@group_event.user == current_user

Upvotes: 0

Dima Melnik
Dima Melnik

Reputation: 884

You should use current_user for this. You can do it everywhere in project. No needs to define variable @currentUser or etc.

You can compare like models

if current_user == @product.user

that is the equivalent to

if current_user.id == @product.user.id

In some cases you can use

if current_user.id == @product.user_id

This prevent extra sql query to load user model

If you are using Devise for authorization and you need control access for actions you should see (maybe use) gem https://github.com/CanCanCommunity/cancancan

https://github.com/airbnb/ruby will help you to stay in tune ;)

Upvotes: 1

KensoDev
KensoDev

Reputation: 3285

I see a few problems here

def index
  @currentUser = current_user.id
end

Other than what @HolyMoly already commented, you should use underscore and not camelcase, if current_user is nil here, .id will fail on it, resulting in an exception.

Second, you are checking "ability" by comparing values of ids, I would change your code to do this

<% if allow_product_delete?(@product) %>

In a helper

def allow_product_delete?(product)
  return false unless current_user
  @product.user_id == current_user.id
end

if you are using devise current_user exists in controller and views, you don't need to define it as an instance variable, it's already defined as a controller method on all actions (by default). so by calling current_user in your views you are done.

If a user is not logged in, current_user will be nil, you always have to prepare for this and protect against it.

Last, I would look into ability gems (cancan or cancancan), those provide a very nice DSL for dealing with what you were trying here.

Upvotes: 13

HolyMoly
HolyMoly

Reputation: 2080

Have you set it up to actually be able to user current_user ? in your code you have :

@currentUser = current_user.id

But where was current_user defined? I haven't used Devise but with sessions you could define the value of current_user with a helper method (you may be able to also do it right there in the sessions_controller #create method), like this:

 def current_user
     @current_user ||= User.find_by(id: session[:user_id])
  end

then throughout your app you could use current_user.id or current_user.name or whatever you needed.

So while sessions is not Devise, I hope this helps .

Upvotes: 3

Alex Antonov
Alex Antonov

Reputation: 15216

First of all, ruby like undescored_rather_than camelCased style.

Secondly, you need two equal signs instead of three. @currentUser == @product.user_id should work

At third, you don't need to compare integer ids, you can compare models, something like that:

<% if current_user == @product.user %>
  <%= link_to "Back", products_path %>
  <%= link_to "Edit", edit_product_path(@product) %>
  <%= link_to "Delete", product_path(@product), method: :delete, data: { confirm: "Are you sure?"} %>
<% end %>

Please note that I omitted the @ in current_user method, because current_user is helper for devise, else I removed unnecessary <% else %> (in my opinion)

Upvotes: 2

Related Questions