sabrams
sabrams

Reputation: 1128

Show link if session user matches certain criteria

I'm trying to make a specific link in my application only visible to users who have the attribute :department equal to "Sales".

In other words, I've got a model Users, in which a user has a password, username, and department. The session saves the :user_id once the user is logged in.

What I would like to do is when my view is rendered, depending on the :department of the logged in user, either display, or don't display a specific link.

Here's the code I've got in my view, but I'm struggling with how to take the session info and find the department of the user from it.

<% if Users.where(id: session[:user_id])[:department] == "Sales" %>
  <%= link_to 'New Request', new_request_path %>
  <% else nil %>
<% end %>

I know it's bad to do a query anywhere other than the controller or model, so if you have any advice on how to better structure this logic as well, I would appreciate it.

Upvotes: 0

Views: 147

Answers (2)

CDub
CDub

Reputation: 13354

I think what you want is:

<% user = User.find_by_id(session[:user_id]) %>
<% if user.present? && user[:department] == "Sales" %>
  <%= link_to 'New Request', new_request_path %>
<% end %>

Personally, I'd put this into a helper method to clean it up:

In app/helpers/users_helper.rb:

def user_in_sales?
  user = User.find_by_id(session[:user_id])

  user.present? && user[:department] == "Sales"
end

Then your view:

<% if user_in_sales? %>
  <%= link_to 'New Request', new_request_path %>
<% end %>

Personally, I'd strongly look into using something like cancan to handle this situation. I think you may find that you could use cancan as an effective authorization tool other places in your app, especially if you're doing logic like this elsewhere.

Upvotes: 1

coreyward
coreyward

Reputation: 80041

First, you're using an object oriented language. It would help you to quit getting hung up on implementation details (e.g. department == "Sales") and instead consider the intent or meaning you're trying to express and code to meet that. For example:

if current_user.works_in?(:jewelry)
  link_to 'Request Receipt', new_request_path
end

Your models should expose a public interface that allows other objects in your code (like your controller) to get the information they need (i.e. whether or not a user has an association with a department) without knowledge of or concern for the underlying data storage schema.

class User
  def works_in?(department_name)
    departments.pluck(:name).include?(department_name.to_s)
  end
end

Upvotes: 1

Related Questions