craftdeer craftdeer - 2 years ago 78
Ruby Question

Using if statement in rails to show a link_to tag based on who is signed in?

beginner in Rails and I am making a rails news page with devise authentication and when someone visits localhost:3000/news, it shows a list of news. I am trying to show "edit" link only if it was posted by current user or if the current user's username is "admin". Here is my code for it

<% @news.each do |element| %>
<p>Title: <%= element.title%></p>
<p><%= element.body%></p>
<li>Posted by: <%= element.user.username %></li>
<li><%= link_to "Comments", newsone_path(element) %></li>
<% if current_user.username == "admin" || current_user == element.user %>
<li><%= link_to "Edit this drink", edit_news_path(element) %></li>
<% end %>
<% end %>

It works and it shows the edit link only if username "admin" is signed in or if the user who posted it is signed in. But if I try to go to
without signing in, it shows an error

"undefined method `username' for nil:NilClass" on line "<% if
current_user.username == "admin" || current_user == element.user %>"

I think this maybe because when I am signed out, there is no username maybe? How do I get around this please help?

Answer Source

Devise here is setting current_user to nil, which doesn't have a method .username.

To get around that, you can check for the existence of current_user before attempting to call that method.

An easy-to-read way is to do this instead:

 <% if current_user && (current_user.username == "admin" || current_user == element.user) %>

In this line you're checking "does current_user exist"? Then, if so, are they an admin? Because of the way that Ruby evaluates boolean logic statements like this, the second part of that line after the && does not get evaluated, and so it doesn't raise an error.

An alternative would be to use the try method, which is a little more complex to understand, but it attempts to run the named method ('try') by referring to it as a symbol (:try):

<% if current_user.try(:username) == "admin" || current_user == element.user %>

As you develop this, you might want to look at the Rolify gem or similar, so that you can have various different named roles, and then one of the permissions gems, such as Pundit, which allows you to define what different types of users can and can't do.

Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download