Welcome to the Treehouse Community

Want to collaborate on code errors? Have bugs you need feedback on? Looking for an extra set of eyes on your latest project? Get support with fellow developers, designers, and programmers of all backgrounds and skill levels here with the Treehouse Community! While you're at it, check out some resources Treehouse students have shared here.

Looking to learn something new?

Treehouse offers a seven day free trial for new students. Get access to thousands of hours of content and join thousands of Treehouse students and alumni in the community today.

Start your free trial

Ruby

TodoList does not have a user_id foreign key

I've been crazy stuck on this!

Here is my failure after I run bin/rspec spec/models/user_spec.rb

Failures:

  1) User relationships should have many todo_lists
     Failure/Error: it { should have_many(:todo_lists) }
       Expected User to have a has_many association called todo_lists         (TodoList does not have a user_id foreign key.)
     # ./spec/models/user_spec.rb:15:in `block (3 levels) in <top   (required)>'

Here is my user_spec.rb

require 'spec_helper'

describe User do
let(:valid_attributes) {
    {
        first_name: "Louis",
        last_name: "Magnotti",
        email: "lamagnotti@yahoo.com",
        password: "treehouse1234",
        password_confirmation: "treehouse1234"
    }
}

context "relationships" do
it { should have_many(:todo_lists) }
  end

context "validations" do
    let(:user) { User.new(valid_attributes) }

    before do
        User.create(valid_attributes)
    end

    it "requires an email" do
        expect(user).to validate_presence_of(:email)
    end

    it "requires a unique email" do
        expect(user).to validate_uniqueness_of(:email)
    end

    it "requires a unique email (case insensitive)" do
        user.email = "LAMAGNOTTI@YAHOO.COM"
        expect(user).to validate_uniqueness_of(:email)
    end

    it "requires the email address to look like an email" do
        user.email = "louis"
        expect(user).to_not be_valid
    end

end

    describe "#downcase_email" do
    it "makes the email attribute lower case" do
        user = User.new(valid_attributes.merge(email:   "LAMAGNOTTI@YAHOO.COM"))
        expect{ user.downcase_email }.to change{ user.email }.
            from("LAMAGNOTTI@YAHOO.COM").
            to("lamagnotti@yahoo.com")
    end

    it "downcases an email before saving" do
      user = User.new(valid_attributes)
      user.email = "LAMAGNOTTI@YAHOO.COM"
      expect(user.save).to be_truthy
      expect(user.email).to eq("lamagnotti@yahoo.com")
        end
    end
end

User.rb Model

class User < ActiveRecord::Base
  has_secure_password

  has_many :todo_lists

  validates :email, presence: true,
                uniqueness: true,
                format: {
                  with: /\A[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]+\z/
                }

  before_save :downcase_email

  def downcase_email
    self.email = email.downcase
  end
end

Todo_list.rb

class TodoList < ActiveRecord::Base
  belongs_to :user
  has_many :todo_items

  validates :title, presence: true
  validates :title, length: { minimum: 3 }
  validates :description, presence: true
  validates :description, length: { minimum: 5 }

  def has_completed_items?
    todo_items.complete.size > 0
  end

  def has_incomplete_items?
    todo_items.incomplete.size > 0
  end 

end

Thank you!

Schema.rb file

ActiveRecord::Schema.define(version: 20140902185757) do

  create_table "todo_items", force: true do |t|
    t.integer  "todo_list_id"
    t.string   "content"
    t.datetime "created_at"
    t.datetime "updated_at"
    t.datetime "completed_at"
  end

   add_index "todo_items", ["todo_list_id"], name: "index_todo_items_on_todo_list_id"

 create_table "todo_lists", force: true do |t|
    t.string   "title"
    t.text     "description"
    t.datetime "created_at"
    t.datetime "updated_at"
  end

  create_table "users", force: true do |t|
    t.string   "first_name"
    t.string   "last_name"
    t.string   "email"
    t.string   "password_digest"
    t.datetime "created_at"
    t.datetime "updated_at"
  end

   add_index "users", ["email"], name: "index_users_on_email"

end
Maciej Czuchnowski
Maciej Czuchnowski
36,441 Points

Can you show the user and todo_list models?

Thanks for taking a look again Maciej! You've been a huge help.

1 Answer

Maciej Czuchnowski
Maciej Czuchnowski
36,441 Points

OK, no I noticed the rest of the error:

TodoList does not have a user_id foreign key

Your todo_list does not seem to have the user_id column (has_many and belongs_to is not enough). Did you add it through a migration? Can you show me the content of schema.rb file?

Just added the schema.rb file for you. Thanks again!

Just fixed it! I noticed I didnt have

    t.integer  "user_id"

in my schema file!

Thank you for all of your help! What is the schema file used for anyways?

Also, although I added that to my schema folder, it doesn't stay? Why not? Every time I run a test it deletes itself!

Correction: I did this and it worked!

    db:migrate:reset=> rake db:drop db:create db:migrate
Maciej Czuchnowski
Maciej Czuchnowski
36,441 Points

You have to add it through migration. Don't modify the schema itself, because it can get messy. Just create a migration that adds this field to the model (just like Jason does in the videos), run rake db:migrate and it will stay forever. Schema file shows you the exact fields of your models in the database.

http://guides.rubyonrails.org/migrations.html