简体   繁体   中英

Undefined method `user' - Extending the Rails Tutorial

I'm working on a Todo List application, everything I've done is from chapter 10 onwards, and i've been using the parts of chapter 11 that I need to get this far. I've already done what I'm trying to do on other sections of the site with buttons only viewable to the user that made the todo list, and the correct users todo's are on the profile page, but for some reason I can't seem to get the same thing working with the static pages controllers home action. Basically, it's 99% finished apart from the correct users todo lists displaying on the home page, depending on if you're logged in, if you're not logged in you see something else.

The whole home.html.erb

<% if logged_in? && current_user?(@todo_list.user) %>

<div class="container">
<div class="row">
    <% @todo_lists.each do |todo_list| %>
        <div class="col-md-8 col-md-offset-2">
            <div class="well">
            <p class="todo_list_title"><%= link_to todo_list.title,   todo_list %></p>
            <p class="todo_list_description"><%= todo_list.description %>
            | <%= link_to "Show", todo_list_path(todo_list) %> 
            | <%= link_to "Edit", edit_todo_list_path(todo_list) %> 
            | <%= link_to 'Delete', todo_list, method: :delete, data: { confirm: 'Are you sure?' } %>
            </p>
            </div>
        </div>

    <% end %>
    <div class="col-md-8 col-md-offset-2">
      <%= link_to "New Todo List", new_todo_list_path, 
                   class: "btn btn-lg btn-primary" %>
    </div>
</div>
</div>

<% else %>
<div class="center jumbotron">
    <h1>Todo List App</h1>

    <%= link_to "Sign up now!", signup_path, class: "btn btn-lg   btn-primary"  %>
</div>
<% end %>

static_pages_controller.rb

With the static_pages_controller home action like this

def home
    @todo_lists = TodoList.all
end

The following are combinations of home.html.erb with the result it gives

<% if logged_in? %> 

this shows all users todo lists

<% if logged_in? && current_user?(@todo_list) %>

this catches the else statement

<% if logged_in? && current_user?(@todo_list.user) %>

undefined method `user' for nil:NilClass

With the static_pages_controller like this

def home
@user = User.find(params[:id])
@todo_lists = TodoList.all
end

or like this ...

class StaticPagesController < ApplicationController

  before_action :logged_in_user
  before_action :correct_user

def home
    @user = User.find(correct_user)
    @todo_lists = @user.todo_lists.paginate(page: params[:page])
end


private

    def logged_in_user
        unless logged_in?
            store_location
            flash[:danger] = "Please log in."
            redirect_to login_url
        end
    end

    def correct_user
        @user = User.find(params[:id])
        redirect_to(root_url) unless current_user?(@user)
    end

end

All three of the above example give this error

Couldn't find User with 'id'=

It seems like any combination of logged_in_user, and correct_user methods under private dont't work, I always seem to end up with one of the above errors, which is a bit frustrating when i've got the users profile working when the correct user is logged in.

I'm sure the answer is dead simple, as it always seems to be, but I can't see it

Regards Shaun

UPDATE

# Returns true if the given user is the current user.
def current_user?(user)
    user == current_user
end

# Define the method current_user
def current_user
    # Returns the current logged-in user (if any).

    if (user_id = session[:user_id])
        @current_user ||= User.find_by(id: user_id)
    elsif (user_id = cookies.signed[:user_id])
        user = User.find_by(id: user_id)
        if user && user.authenticated?(:remember, cookies[:remember_token])
            log_in user
            @current_user = user
        end
    end
end

We'll need the full error message (along with the first few lines of the stack trace / file & line identifiers) in order to give you a more precise answer. But based on what you've shared, I'm guessing one of two things are true:

  1. Your @todo_list object is nil or wasn't defined properly. Check in the controller; I see you defined @todo_lists (note the plural) but if you didn't define @todo_list then it will default to nil , and of course nil doesn't know the method .user so you'll get an error.
  2. If you're sure (and can prove) that @todo_list is indeed defined and is a TodoList object as expected, it's possible that TodoList objects don't know the .user method. You can verify this by going into the Rails console, creating a new TodoList object, and trying to call .user on it; if you get an error there, you'll definitely get an error in the above view templates. In ActiveRecord, you'd likely fix this by telling TodoList.rb that it belongs_to :user - this should add the necessary method.

Incidentally, I'm skeptical about how you're using that current_user? method. It looks like the first time you call it, you pass in the @todo_list object... even if it's defined properly, how can you expect a TodoList object to be the current user? Why are you even calling that method with that object?

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM