Jay Yang
Jay Yang

Reputation: 89

Why is Rails giving me this NoMethodError?

I am trying to make a profile page with my image repository and I am running into this error:

undefined method `images' for nil:NilClass

def show
        @user = User.find_by(username: params[:username])
        @images = @user.images.order(created_at: :desc) <<< (ERROR is occurring here)
    end

I looked everywhere to find the source of the problem, but I could not find it. I think I am missing something—I am new to rails. My routes are defined as such:

Rails.application.routes.draw do
  resources :images
  devise_for :users
  get '/upload', to: 'images#new'
  root 'images#index'

  get '/@image.user.full_name', to: 'users#show', as: :profile
  resources :images, only: [:index, :show, :create]

  delete 'images/:id(.:format)', :to => 'images#destroy'
end

Here is my users controller file:

class UsersController < ApplicationController
    def show
        @user = User.find_by(username: params[:username])
        @images = @user.images.order(created_at: :desc)
    end
end

And here is my users model:

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

  validates :username, presence: true, uniqueness: { case_sensitive: false }
  validates :first_name, presence: true
  validates :last_name, presence: true

  has_many :images

  def full_name
    [first_name, last_name].join(' ')
  end
end

Here is a part of the schema:

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.string "username", null: false
    t.string "first_name", null: false
    t.string "last_name", null: false
    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
    t.index ["username"], name: "index_users_on_username", unique: true
  end

Any help would be greatly appreciated. Thanks!

Upvotes: 1

Views: 124

Answers (1)

spickermann
spickermann

Reputation: 106782

When you get an undefined method 'images' for nil:NilClass then that means you call images on something that is nil.

In your code example, you have the following lines

@user = User.find_by(username: params[:username])
@images = @user.images.order(created_at: :desc)

in which you call images on @user and get that error. This means @user must be nil at that point. Since you assigned something to @user the line before that assignment must have assign nil to @user. The only reason why that might happen is when User.find_by(username: params[:username]) was nil.

Seems like params[:username] didn't include a username that exists in your database it that params[:username] was not set at all.

Upvotes: 1

Related Questions