user5083315
user5083315

Reputation:

Undefined local variable/method User

I'm learning how to seed data into my project using the faker gem currently. My project is a todo list that allows users to checkoff and add items. I learned how to create my own RandomData but I'm having trouble adapting a gem into the tutorial. I also am not sure if I'm 'adapting' this to the tutorial correctly so I hope I provide enough information.

When running rake db:reset error is as follows:

NameError: undefined local variable or method `user' for main:Object
itoff/db/seeds.rb:13:in `block in <top (required)>'
itoff/db/seeds.rb:11:in `times'
itoff/db/seeds.rb:11:in `<top (required)>'

I see that it's in my fake items loop, but I'm not sure what I'm doing wrong. Keep in mind I'm very new at Ruby on Rails, so my apologies if I'm missing something obvious.

Using devise and faker gems.

(Question at the end: What can I do better? What else should I work/focus on to get better at ruby on rails?)

seeds.rb:

#Create fake user
5.times do
  user = User.new(
    email: Faker::Internet.email,
    password: Faker::Lorem.characters(10)
  )
  user.skip_confirmation!
  user.save!
end

#Create fake items
10.times do
  item = Item.create!(
    user: user.sample,
    name: Faker::Lorem.sentence
  )
end

puts "Seed finished"
puts "#{User.count} users created"
puts "#{Item.count} items created"

my items_controller.rb:

class ItemsController < ApplicationController

  def create
    @item = current_user.items.new(item_params)

    if @item.save
      redirect_to current_user, notice: "Item was saved successfully."
    else
      flash[:error] = "Error creating item. Please try again."
      render :new
    end
  end


  def destroy
     @item = Item.find(params[:id])

     if @item.destroy
       flash[:notice] = "\"#{@item.name}\" was deleted successfully."
       redirect_to action: :index
     else
       flash[:error] = "There was an error deleting the item."
       render :show
     end
   end

  private
  def item_params
    params.require(:item).permit(:name)
  end
end

item.rb:

class Item < ActiveRecord::Base
  belongs_to :user
  validates :description, presence: true
end

user.rb:

class User < ActiveRecord::Base
  devise :database_authenticatable, :registerable,
         :recoverable, :rememberable, :trackable, :validatable, :confirmable

         has_many :items
end

Upvotes: 1

Views: 1054

Answers (1)

Dbz
Dbz

Reputation: 2761

There are two issues. There error is because your user variable in the seeds.rb file is out of scope. It is inside of a do block. Moreover, you should user the User class, not an instance:

5.times do
  user = User.new( # This is inside of a do block
    email: Faker::Internet.email,
    password: Faker::Lorem.characters(10)
  )
  user.skip_confirmation!
  user.save!
end

#Create fake items
10.times do
  item = Item.create!(
    user: user.sample, # Which user? There is no user in this scope
    name: Faker::Lorem.sentence
  )
end

What you need to do is call .sample on the User class; however, you can't just pluck a user that way. You need to grab a random id:

#Create fake items
user_ids = User.ids # See the capitalization of User
10.times do
  item = Item.create!(
    user_id: user_ids.sample,
    name: Faker::Lorem.sentence
  )
end

Alternatively to grabbing an id out of all of the ids. You can do this: User.order("RANDOM()").first, and that will grab a random User model. This would be:

#Create fake items
10.times do
  item = Item.create!(
    user: User.order("RANDOM()").first
    name: Faker::Lorem.sentence
  )
end

Upvotes: 1

Related Questions