undefined method `username' for nil:NilClass w

2019-09-15 03:18发布

Whenever I try to log in and sign up, I am hit with this error:

undefined method `username' for nil:NilClass

on these two lines:

<strong><%= @user.username %></strong> <br>
<strong><%= @user.name %></strong>

Here is the full error from the server's output:

User Load (0.3ms)  SELECT "users".* FROM "users" WHERE "users"."username" = 'sign_in' LIMIT 1
  Rendered users/show.html.erb within layouts/application (2.1ms)
Completed 500 Internal Server Error in 7ms

ActionView::Template::Error (undefined method `username' for nil:NilClass):
    1: <strong><%= @user.username %></strong> <br>
    2: <strong><%= @user.name %></strong>
    3: <%= debug @user %>
    4: 
  app/views/users/show.html.erb:1:in `_app_views_users_show_html_erb__1133891108745893964_2164088020'

Here are my routes:

Stynyl::Application.routes.draw do
  resources :things
  resources :users, only: [:show]

  devise_for :users
  get '/about', to: 'pages#about'
  root 'things#index'
end

Here is my user show view

<strong><%= @user.username %></strong> <br>
<strong><%= @user.name %></strong>



<div id="things" class="transitions-enabled">
  <% @user.things.each do |thing| %>
    <div class='panel panel default'>
    <div class="box">
      <%= link_to image_tag(thing.image.url(:medium)), thing %>
      <div class='panel-body'>
      <strong><p><%= thing.title %></p></strong>
      <p><%= thing.description %></p>
      By <%= link_to thing.user.username, thing.user %>

      <% if thing.user == current_user %>
        <%= link_to edit_thing_path(thing) do %>
        <span class='glyphicon glyphicon-edit'></span> Edit
      <% end %>
      <%= link_to thing_path(thing), method: :delete, data: { confirm: 'Are you sure?' } do %>
        <span class='glyphicon glyphicon-trash'></span> Delete
      <% end %>
      </div>
      <% end %>
      </div>
    </div>
  <% end %>
</div>

Here is my UsersController file:

class UsersController < ApplicationController
  def show
    @user = User.find_by_username(params[:id])
  end
end

Output of rake routes:

            Prefix Verb   URI Pattern                    Controller#Action
                  things GET    /things(.:format)              things#index
                         POST   /things(.:format)              things#create
               new_thing GET    /things/new(.:format)          things#new
              edit_thing GET    /things/:id/edit(.:format)     things#edit
                   thing GET    /things/:id(.:format)          things#show
                         PATCH  /things/:id(.:format)          things#update
                         PUT    /things/:id(.:format)          things#update
                         DELETE /things/:id(.:format)          things#destroy
                   users POST   /users(.:format)               users#create
                new_user GET    /users/new(.:format)           users#new
                    user GET    /users/:id(.:format)           users#show
        new_user_session GET    /users/sign_in(.:format)       devise/sessions#new
            user_session POST   /users/sign_in(.:format)       devise/sessions#create
    destroy_user_session DELETE /users/sign_out(.:format)      devise/sessions#destroy
           user_password POST   /users/password(.:format)      devise/passwords#create
       new_user_password GET    /users/password/new(.:format)  devise/passwords#new
      edit_user_password GET    /users/password/edit(.:format) devise/passwords#edit
                         PATCH  /users/password(.:format)      devise/passwords#update
                         PUT    /users/password(.:format)      devise/passwords#update
cancel_user_registration GET    /users/cancel(.:format)        devise/registrations#cancel
       user_registration POST   /users(.:format)               devise/registrations#create
   new_user_registration GET    /users/sign_up(.:format)       devise/registrations#new
  edit_user_registration GET    /users/edit(.:format)          devise/registrations#edit
                         PATCH  /users(.:format)               devise/registrations#update
                         PUT    /users(.:format)               devise/registrations#update
                         DELETE /users(.:format)               devise/registrations#destroy
                   about GET    /about(.:format)               pages#about
                    root GET    /                              things#index

Edits

  1. I also noticed that when I delete all of the code from the User show view, I can get to the signup and login pages, but they are blank. Can we safely guarantee that the problem is in the view? I'm so perplexed at how something in the show view can affect the ability to sign in and sign up!
  2. I have also observed that when I add content to the users show view, it appears on the sign up and login pages. What on earth is going on?

1条回答
仙女界的扛把子
2楼-- · 2019-09-15 04:04

The reason is because of a conflict in your routes. When matching a request to a route, Rails will go through your routes sequentially. But your order shows:

user GET                /users/:id(.:format)           users#show
new_user_session GET    /users/sign_in(.:format)       devise/sessions#new

And so Rails is passing sign_in as the :id parameter to your user show method, instead of being caught by devise's new_user_session_path. Changing the order will fix the problem.

TL:DR; devise_for :users should be declared before resources :users.

查看更多
登录 后发表回答