user9818523
user9818523

Reputation:

I need current user to see only his todo list and got an error: undefined method `lists' for nil:NilClass

I need the current user to see only his own todo list after login. (Using Devise) And I got error "Undefined method "lists" for nil:NilClass. I made changes in the User model (has_many :lists), as well in the List model (belongs_to :user). I got an error undefined method `lists' for nil:NilClass

Lists Controller code is

class ListsController < ApplicationController  
    before_action :authenticate_user!, except: [:index]

    def index
        @lists = current_user.lists.order('created_at') <----- error occurs here
    end 

    def new
        @list = current_user.lists.new
    end

    def create
        @list = current_user.lists.new list_params

        @list.save

        redirect_to lists_path
    end

    def edit
        @list = List.find params[:id]
    end

    def update
        @list = List.find params[:id]

        @list.update list_params

        redirect_to lists_path
    end

    def destroy
        @list = List.find params[:id]

        @list.destroy

        redirect_to lists_path
    end

    private

    def list_params
        params.require(:list).permit(:title)
    end

end

schema.rb code

ActiveRecord::Schema.define(version: 2020_05_10_131407) do

  create_table "lists", force: :cascade do |t|
    t.string "title"
    t.datetime "created_at", precision: 6, null: false
    t.datetime "updated_at", precision: 6, null: false
    t.integer "user_id"
  end

  create_table "tasks", force: :cascade do |t|
    t.string "title"
    t.boolean "completed"
    t.integer "list_id"
    t.datetime "created_at", precision: 6, null: false
    t.datetime "updated_at", precision: 6, null: false
    t.index ["list_id"], name: "index_tasks_on_list_id"
  end

  create_table "users", force: :cascade do |t|
    t.string "email", default: "", null: false
    t.string "encrypted_password", default: "", null: false
    t.string "reset_password_token"
    t.datetime "reset_password_sent_at"
    t.datetime "remember_created_at"
    t.datetime "created_at", precision: 6, null: false
    t.datetime "updated_at", precision: 6, null: false
    t.index ["email"], name: "index_users_on_email", unique: true
    t.index ["reset_password_token"], name: "index_users_on_reset_password_token", unique: true
  end

end

And Index.html code if need

<div class="col-md-12">
    <h1>ToDo List</h1>

    <div class="buffer-top"><%= link_to "New List", new_list_path, class: 'btn btn-primary' %></div>

    <div class="buffer-top">
        <% @lists.each do |list| %>
            <%= render partial: 'list', object: list %>
        <% end %>
    </div>

</div>

Upvotes: 0

Views: 54

Answers (1)

Rockwell Rice
Rockwell Rice

Reputation: 3002

You are not authenticating the User for the index view, the error is because there is no current_user, so you are calling the method lists on nil.

You should check if there is a user first

def index
  if user_signed_in?
   @lists = current_user.lists.order('created_at')
  else
    <!-- Do somthing here, what do you want if no user is there? -->
  end
end

Not exactly sure what you would want if there is no user so you'll have to fill that part in. The issue really here is you are basically creating a view where you want a user, but you also do not require a user, the user's @lists would likely be better served on a different view if you do not want to require a user here.

You will also have to fix the view to check as well.

<% if user_signed_in? %>
  <div class="buffer-top">
    <% @lists.each do |list| %>
        <%= render partial: 'list', object: list %>
    <% end %>
  </div>
<% end %>

If you really want to go with this setup then you could DRY it up by removing the lines inside the index method and changing the view.

<% if user_signed_in? %>
  <div class="buffer-top">
    <% current_user.lists.order('created_at').each do |list| %>
        <%= render partial: 'list', object: list %>
    <% end %>
  </div>
<% end %>

Upvotes: 1

Related Questions