Search code examples
ruby-on-railslayoutnomethoderror

Rails undefined method in _header.html.erb


I'm using layout/_header.html.erb to create a navigation bar/log in and sign up bar to appear on everyone page of my app. It works fine until a user signs in and then I get a no method error (when a user is signed in, I want the "login" function to change to "logout"). I believe that this is something to do with not being able to call a method outside of it's own controller but I'm not sure how to go about fixing this, if anyone could point me in the right direction I'd be very happy.

Error message:

NoMethodError in Users#index

Showing /home/stephen/ruby/friendlyaccess/app/views/layouts/_header.html.erb where line #14 raised:

undefined method `user_type' for nil:NilClass

Extracted source (around line #14):


<div id="usernav">
<ul>
  <% if user_signed_in? && @user.user_type == 'client' %>
    <li><%= link_to "Edit Details", edit_user_registration_path %></li>
    <li><%= link_to "Sign Out", destroy_user_session_path, :method => :delete %></li>
  <% else if user_signed_in? && @user.user_type == 'company' %>

_header.html.erb:

<div id="navbar">
<table>
<tr>
  <th><%= link_to "Home", root_path %></th>
  <th><%= link_to "Service Index", users_path %></th>
  <th><%= link_to "About Friendly Access" %></th>
  <th><%= link_to "Contact Us" %></th>
</tr>

<div id="usernav">
<ul>
  <% if user_signed_in? && @user.user_type == 'client' %>
    <li><%= link_to "Edit Details", edit_user_registration_path %></li>
     <li><%= link_to "Sign Out", destroy_user_session_path, :method => :delete %></li>
  <% else if user_signed_in? && @user.user_type == 'company' %>
    <li><%= link_to "Edit Details", edit_user_registration_path %></li>
    <li><%= link_to "View Profile", show_user_path %></li>
    <li><%= link_to "Sign Out", destroy_user_session_path, :method => :delete %></li>
  <% else %>
    <li><%= link_to "Sign Up", new_user_registration_path, class: "active" %></li>
    <li><%= link_to "Sign In", new_user_session_path, class: "active" %></li>
  <% end %>
<% end %>
</ul>
</div>

users_controller.rb:

class UsersController < ApplicationController
  before_action :set_user, only: [:show, :edit, :update, :destroy]
  before_action :authenticate_user!, except: [:index, :show]

  def index
if params[:search]
  @users = User.search(params[:search].capitalize).order("company_name ASC")
elsif params[:company_type]
  @users = User.search(params[:company_type]).order("company_name ASC")
elsif params[:letter]
  @users = User.search(params[:letter]).order("company_name ASC")
else
  @users = User.all.order("company_name ASC")
end 
  end

  def show
  end

private

  def set_user
    @user = User.find(params[:id])
  end

  def user_params
    params.require(:user).permit(:company_name, :company_type, :photo)
  end

end

user.rb:

class User < ActiveRecord::Base
  # Include default devise modules. Others available are:
  # :confirmable, :lockable, :timeoutable and :omniauthable
  devise :database_authenticatable, :registerable,
     :recoverable, :rememberable, :trackable, :validatable

  mount_uploader :photo, PhotoUploader

  before_save :capitalize_attributes

  def self.search(query)
    where("company_name like ? OR company_type like ?", "%#{query}%", "%#{query}%")  
  end

  def capitalize_attributes
 capitalizable = ["first_name","last_name", "city", "company_name"]
 self.attributes.each do |attr,val|
   #based on comment either of these will work
   #if you want to store nil in the DB then
   self.send("#{attr}=",val.strip.capitalize) if capitalizable.include?(attr) && !val.nil?
   #if you want to store a blank string in the DB then 
   self.send("#{attr}=",val.to_s.strip.capitalize) if capitalizable.include?(attr)
     end
   end

end

Solution

  • Change your before_action :set_user like below to allow index action

    before_action :set_user, only: [:index, :show, :edit, :update, :destroy]
    

    to use set_user method so that @user will be available for index.

    OR

    Use current_user instead of @user as @user is not initialized for index action.

    <div id="usernav">
    <ul>
      <% if user_signed_in? && current_user.user_type == 'client' %>
        <li><%= link_to "Edit Details", edit_user_registration_path %></li>
         <li><%= link_to "Sign Out", destroy_user_session_path, :method => :delete %></li>
      <% else if user_signed_in? && current.user_type == 'company' %>
        <li><%= link_to "Edit Details", edit_user_registration_path %></li>
        <li><%= link_to "View Profile", show_user_path %></li>
        <li><%= link_to "Sign Out", destroy_user_session_path, :method => :delete %></li>
      <% else %>
        <li><%= link_to "Sign Up", new_user_registration_path, class: "active" %></li>
        <li><%= link_to "Sign In", new_user_session_path, class: "active" %></li>
      <% end %>
    <% end %>
    </ul>
    </div>