ActiveModel::MissingAttributeError: can't write unknown attribute `user_id`
You have the wrong migration - instead of adding a user_id
to comments
you add users.commed
.
Oops. It can happen to the best of us.
So first let's create a migration to clean up this mistake:
class RemoveCommedFromUsers < ActiveRecord::Migration
def change
remove_column :users, :commed # will also remove the index
end
end
Of course if the App has not been deployed you could just delete the offending migration and run rake db:reset
So lets create the correct migration
rails g migration AddUserToComments user:belongs_to
Which generates the following migration:
class AddUserToComments < ActiveRecord::Migration
def change
add_reference :comments, :user, index: true
end
end
add_reference
creates a index and a foreign key in one sweep.
Jonathan Musso
Motorcycle and Hotrod enthusiast. Full Stack Rails student at Bloc.io.
Updated on June 05, 2022Comments
-
Jonathan Musso almost 2 years
I am trying to implement a "comment" feature as part of my assignment for an project I am building.
Earlier in the course we created a comment table and had the Faker gem generate fake comments.
My instructions are as follows:
Comments must be associated with users, so add a user_id foreign key to the comments table. Remember to add an index to it too;
Update the User model so you can call user.comments, and the Comment model so you can call comment.user;
Modify the seeds.rb file to create valid comments when you run db:reset;
Initially I tried to run my rails generate commands but kept running into this error:
▶ rake db:migrate == 20150508143445 CreateComments: migrating =================================== -- create_table(:comments) rake aborted! StandardError: An error has occurred, this and all later migrations canceled: SQLite3::SQLException: table "comments" already exists: CREATE TABLE "comments" ("id" INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, "description" text, "created_at" datetime NOT NULL, "updated_at" datetime NOT NULL) /Users/jon/code/bloccit/db/migrate/20150508143445_create_comments.rb:3:in `change' -e:1:in `<main>' ActiveRecord::StatementInvalid: SQLite3::SQLException: table "comments" already exists: CREATE TABLE "comments" ("id" INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, "description" text, "created_at" datetime NOT NULL, "updated_at" datetime NOT NULL) /Users/jon/code/bloccit/db/migrate/20150508143445_create_comments.rb:3:in `change' -e:1:in `<main>' SQLite3::SQLException: table "comments" already exists /Users/jon/code/bloccit/db/migrate/20150508143445_create_comments.rb:3:in `change' -e:1:in `<main>' Tasks: TOP => db:migrate (See full trace by running task with --trace)
So I discovered that I needed to delete the old table from the start of the course. I did this in the console.
ActiveRecord::Base.connection.execute("drop table comments")
It seemed to work. I was then able to run these in terminal.
▶ rake db:migrate == 20150508143445 CreateComments: migrating =================================== -- create_table(:comments) -> 0.0015s == 20150508143445 CreateComments: migrated (0.0016s) ========================== == 20150508152354 DropComments: migrating ===================================== == 20150508152354 DropComments: migrated (0.0000s) ============================ ▶ rails g migration AddCommentToUsers commed_id:integer:index invoke active_record create db/migrate/20150508155200_add_comment_to_users.rb ▶ rake db:migrate == 20150508155200 AddCommentToUsers: migrating ================================ -- add_column(:users, :commed_id, :integer) -> 0.0010s -- add_index(:users, :commed_id) -> 0.0012s == 20150508155200 AddCommentToUsers: migrated (0.0023s) =======================
models/comment.rb
class Comment < ActiveRecord::Base belongs_to :user end
models/user.rb
class User < ActiveRecord::Base # Include default devise modules. Others available are: # :confirmable, :lockable, :timeoutable and :omniauthable devise :database_authenticatable, :registerable, :recoverable, :rememberable, :trackable, :validatable, :confirmable has_many :posts has_many :comments # CarrierWave method for attribute functionality mount_uploader :avatar, AvatarUploader # These methods check the role of a user in the database def admin? role == 'admin' end def moderator? role == 'moderator' end end
migrations/create_comments.rb
class CreateComments < ActiveRecord::Migration def change create_table :comments do |t| t.text :description t.timestamps null: false end end end
migrations/add_comment_to_users.rb
class AddCommentToUsers < ActiveRecord::Migration def change add_column :users, :commed_id, :integer add_index :users, :commed_id end end
In my seeds.rb I have changed
# Create Comments 50.times do Comment.create!( # user: users.sample, # we have not yet associated Users with Comments post: posts.sample, description: Faker::Lorem.paragraph ) end
to
# Create Comments 50.times do Comment.create!( user: users.sample, description: Faker::Lorem.paragraph ) end
Now when I run rake db:reset I get this error.
▶ rake db:reset -- create_table("advertisements", {:force=>:cascade}) -> 0.0047s -- create_table("answers", {:force=>:cascade}) -> 0.0010s -- add_index("answers", ["question_id"], {:name=>"index_answers_on_question_id"}) -> 0.0014s -- create_table("comments", {:force=>:cascade}) -> 0.0010s -- create_table("posts", {:force=>:cascade}) -> 0.0010s -- add_index("posts", ["topic_id"], {:name=>"index_posts_on_topic_id"}) -> 0.0010s -- add_index("posts", ["user_id"], {:name=>"index_posts_on_user_id"}) -> 0.0014s -- create_table("questions", {:force=>:cascade}) -> 0.0010s -- create_table("summaries", {:force=>:cascade}) -> 0.0010s -- add_index("summaries", ["post_id"], {:name=>"index_summaries_on_post_id"}) -> 0.0010s -- create_table("topics", {:force=>:cascade}) -> 0.0036s -- create_table("users", {:force=>:cascade}) -> 0.0015s -- add_index("users", ["commed_id"], {:name=>"index_users_on_commed_id"}) -> 0.0009s -- add_index("users", ["comment_id"], {:name=>"index_users_on_comment_id"}) -> 0.0012s -- add_index("users", ["email"], {:name=>"index_users_on_email", :unique=>true}) -> 0.0015s -- add_index("users", ["reset_password_token"], {:name=>"index_users_on_reset_password_token", :unique=>true}) -> 0.0017s -- initialize_schema_migrations_table() -> 0.0034s rake aborted! ActiveModel::MissingAttributeError: can't write unknown attribute `user_id` /Users/jon/code/Bloccit/db/seeds.rb:45:in `block in <top (required)>' /Users/jon/code/Bloccit/db/seeds.rb:44:in `times' /Users/jon/code/Bloccit/db/seeds.rb:44:in `<top (required)>' -e:1:in `<main>' Tasks: TOP => db:setup => db:seed (See full trace by running task with --trace)
Here is the full stack trace:
ActiveModel::MissingAttributeError: can't write unknown attribute `user_id` /Users/jon/.rvm/rubies/ruby-2.2.1/lib/ruby/gems/2.2.0/gems/activerecord-4.2.1/lib/active_record/attribute.rb:138:in `with_value_from_database' /Users/jon/.rvm/rubies/ruby-2.2.1/lib/ruby/gems/2.2.0/gems/activerecord-4.2.1/lib/active_record/attribute_set.rb:39:in `write_from_user' /Users/jon/.rvm/rubies/ruby-2.2.1/lib/ruby/gems/2.2.0/gems/activerecord-4.2.1/lib/active_record/attribute_methods/write.rb:74:in `write_attribute_with_type_cast' /Users/jon/.rvm/rubies/ruby-2.2.1/lib/ruby/gems/2.2.0/gems/activerecord-4.2.1/lib/active_record/attribute_methods/write.rb:56:in `write_attribute' /Users/jon/.rvm/rubies/ruby-2.2.1/lib/ruby/gems/2.2.0/gems/activerecord-4.2.1/lib/active_record/attribute_methods/dirty.rb:96:in `write_attribute' /Users/jon/.rvm/rubies/ruby-2.2.1/lib/ruby/gems/2.2.0/gems/activerecord-4.2.1/lib/active_record/attribute_methods.rb:373:in `[]=' /Users/jon/.rvm/rubies/ruby-2.2.1/lib/ruby/gems/2.2.0/gems/activerecord-4.2.1/lib/active_record/associations/belongs_to_association.rb:83:in `replace_keys' /Users/jon/.rvm/rubies/ruby-2.2.1/lib/ruby/gems/2.2.0/gems/activerecord-4.2.1/lib/active_record/associations/belongs_to_association.rb:14:in `replace' /Users/jon/.rvm/rubies/ruby-2.2.1/lib/ruby/gems/2.2.0/gems/activerecord-4.2.1/lib/active_record/associations/singular_association.rb:17:in `writer' /Users/jon/.rvm/rubies/ruby-2.2.1/lib/ruby/gems/2.2.0/gems/activerecord-4.2.1/lib/active_record/associations/builder/association.rb:123:in `user=' /Users/jon/.rvm/rubies/ruby-2.2.1/lib/ruby/gems/2.2.0/gems/activerecord-4.2.1/lib/active_record/attribute_assignment.rb:54:in `public_send' /Users/jon/.rvm/rubies/ruby-2.2.1/lib/ruby/gems/2.2.0/gems/activerecord-4.2.1/lib/active_record/attribute_assignment.rb:54:in `_assign_attribute' /Users/jon/.rvm/rubies/ruby-2.2.1/lib/ruby/gems/2.2.0/gems/activerecord-4.2.1/lib/active_record/attribute_assignment.rb:41:in `block in assign_attributes' /Users/jon/.rvm/rubies/ruby-2.2.1/lib/ruby/gems/2.2.0/gems/activerecord-4.2.1/lib/active_record/attribute_assignment.rb:35:in `each' /Users/jon/.rvm/rubies/ruby-2.2.1/lib/ruby/gems/2.2.0/gems/activerecord-4.2.1/lib/active_record/attribute_assignment.rb:35:in `assign_attributes' /Users/jon/.rvm/rubies/ruby-2.2.1/lib/ruby/gems/2.2.0/gems/activerecord-4.2.1/lib/active_record/core.rb:559:in `init_attributes' /Users/jon/.rvm/rubies/ruby-2.2.1/lib/ruby/gems/2.2.0/gems/activerecord-4.2.1/lib/active_record/core.rb:281:in `initialize' /Users/jon/.rvm/rubies/ruby-2.2.1/lib/ruby/gems/2.2.0/gems/activerecord-4.2.1/lib/active_record/inheritance.rb:61:in `new' /Users/jon/.rvm/rubies/ruby-2.2.1/lib/ruby/gems/2.2.0/gems/activerecord-4.2.1/lib/active_record/inheritance.rb:61:in `new' /Users/jon/.rvm/rubies/ruby-2.2.1/lib/ruby/gems/2.2.0/gems/activerecord-4.2.1/lib/active_record/persistence.rb:50:in `create!' /Users/jon/code/Bloccit/db/seeds.rb:45:in `block in <top (required)>' /Users/jon/code/Bloccit/db/seeds.rb:44:in `times' /Users/jon/code/Bloccit/db/seeds.rb:44:in `<top (required)>' /Users/jon/.rvm/rubies/ruby-2.2.1/lib/ruby/gems/2.2.0/gems/activesupport-4.2.1/lib/active_support/dependencies.rb:268:in `load' /Users/jon/.rvm/rubies/ruby-2.2.1/lib/ruby/gems/2.2.0/gems/activesupport-4.2.1/lib/active_support/dependencies.rb:268:in `block in load' /Users/jon/.rvm/rubies/ruby-2.2.1/lib/ruby/gems/2.2.0/gems/activesupport-4.2.1/lib/active_support/dependencies.rb:240:in `load_dependency' /Users/jon/.rvm/rubies/ruby-2.2.1/lib/ruby/gems/2.2.0/gems/activesupport-4.2.1/lib/active_support/dependencies.rb:268:in `load' /Users/jon/.rvm/rubies/ruby-2.2.1/lib/ruby/gems/2.2.0/gems/railties-4.2.1/lib/rails/engine.rb:547:in `load_seed' /Users/jon/.rvm/rubies/ruby-2.2.1/lib/ruby/gems/2.2.0/gems/activerecord-4.2.1/lib/active_record/tasks/database_tasks.rb:250:in `load_seed' /Users/jon/.rvm/rubies/ruby-2.2.1/lib/ruby/gems/2.2.0/gems/activerecord-4.2.1/lib/active_record/railties/databases.rake:180:in `block (2 levels) in <top (required)>' /Users/jon/.rvm/rubies/ruby-2.2.1/lib/ruby/2.2.0/rake/task.rb:240:in `call' /Users/jon/.rvm/rubies/ruby-2.2.1/lib/ruby/2.2.0/rake/task.rb:240:in `block in execute' /Users/jon/.rvm/rubies/ruby-2.2.1/lib/ruby/2.2.0/rake/task.rb:235:in `each' /Users/jon/.rvm/rubies/ruby-2.2.1/lib/ruby/2.2.0/rake/task.rb:235:in `execute' /Users/jon/.rvm/rubies/ruby-2.2.1/lib/ruby/2.2.0/rake/task.rb:179:in `block in invoke_with_call_chain' /Users/jon/.rvm/rubies/ruby-2.2.1/lib/ruby/2.2.0/monitor.rb:211:in `mon_synchronize' /Users/jon/.rvm/rubies/ruby-2.2.1/lib/ruby/2.2.0/rake/task.rb:172:in `invoke_with_call_chain' /Users/jon/.rvm/rubies/ruby-2.2.1/lib/ruby/2.2.0/rake/task.rb:201:in `block in invoke_prerequisites' /Users/jon/.rvm/rubies/ruby-2.2.1/lib/ruby/2.2.0/rake/task.rb:199:in `each' /Users/jon/.rvm/rubies/ruby-2.2.1/lib/ruby/2.2.0/rake/task.rb:199:in `invoke_prerequisites' /Users/jon/.rvm/rubies/ruby-2.2.1/lib/ruby/2.2.0/rake/task.rb:178:in `block in invoke_with_call_chain' /Users/jon/.rvm/rubies/ruby-2.2.1/lib/ruby/2.2.0/monitor.rb:211:in `mon_synchronize' /Users/jon/.rvm/rubies/ruby-2.2.1/lib/ruby/2.2.0/rake/task.rb:172:in `invoke_with_call_chain' /Users/jon/.rvm/rubies/ruby-2.2.1/lib/ruby/2.2.0/rake/task.rb:165:in `invoke' /Users/jon/.rvm/rubies/ruby-2.2.1/lib/ruby/gems/2.2.0/gems/activerecord-4.2.1/lib/active_record/railties/databases.rake:139:in `block (2 levels) in <top (required)>' /Users/jon/.rvm/rubies/ruby-2.2.1/lib/ruby/2.2.0/rake/task.rb:240:in `call' /Users/jon/.rvm/rubies/ruby-2.2.1/lib/ruby/2.2.0/rake/task.rb:240:in `block in execute' /Users/jon/.rvm/rubies/ruby-2.2.1/lib/ruby/2.2.0/rake/task.rb:235:in `each' /Users/jon/.rvm/rubies/ruby-2.2.1/lib/ruby/2.2.0/rake/task.rb:235:in `execute' /Users/jon/.rvm/rubies/ruby-2.2.1/lib/ruby/2.2.0/rake/task.rb:179:in `block in invoke_with_call_chain' /Users/jon/.rvm/rubies/ruby-2.2.1/lib/ruby/2.2.0/monitor.rb:211:in `mon_synchronize' /Users/jon/.rvm/rubies/ruby-2.2.1/lib/ruby/2.2.0/rake/task.rb:172:in `invoke_with_call_chain' /Users/jon/.rvm/rubies/ruby-2.2.1/lib/ruby/2.2.0/rake/task.rb:165:in `invoke' /Users/jon/.rvm/rubies/ruby-2.2.1/lib/ruby/2.2.0/rake/application.rb:150:in `invoke_task' /Users/jon/.rvm/rubies/ruby-2.2.1/lib/ruby/2.2.0/rake/application.rb:106:in `block (2 levels) in top_level' /Users/jon/.rvm/rubies/ruby-2.2.1/lib/ruby/2.2.0/rake/application.rb:106:in `each' /Users/jon/.rvm/rubies/ruby-2.2.1/lib/ruby/2.2.0/rake/application.rb:106:in `block in top_level' /Users/jon/.rvm/rubies/ruby-2.2.1/lib/ruby/2.2.0/rake/application.rb:115:in `run_with_threads' /Users/jon/.rvm/rubies/ruby-2.2.1/lib/ruby/2.2.0/rake/application.rb:100:in `top_level' /Users/jon/.rvm/rubies/ruby-2.2.1/lib/ruby/2.2.0/rake/application.rb:78:in `block in run' /Users/jon/.rvm/rubies/ruby-2.2.1/lib/ruby/2.2.0/rake/application.rb:176:in `standard_exception_handling' /Users/jon/.rvm/rubies/ruby-2.2.1/lib/ruby/2.2.0/rake/application.rb:75:in `run' /Users/jon/code/Bloccit/bin/rake:8:in `<top (required)>' /Users/jon/.rvm/rubies/ruby-2.2.1/lib/ruby/gems/2.2.0/gems/activesupport-4.2.1/lib/active_support/dependencies.rb:268:in `load' /Users/jon/.rvm/rubies/ruby-2.2.1/lib/ruby/gems/2.2.0/gems/activesupport-4.2.1/lib/active_support/dependencies.rb:268:in `block in load' /Users/jon/.rvm/rubies/ruby-2.2.1/lib/ruby/gems/2.2.0/gems/activesupport-4.2.1/lib/active_support/dependencies.rb:240:in `load_dependency' /Users/jon/.rvm/rubies/ruby-2.2.1/lib/ruby/gems/2.2.0/gems/activesupport-4.2.1/lib/active_support/dependencies.rb:268:in `load' /Users/jon/.rvm/rubies/ruby-2.2.1/lib/ruby/site_ruby/2.2.0/rubygems/core_ext/kernel_require.rb:54:in `require' /Users/jon/.rvm/rubies/ruby-2.2.1/lib/ruby/site_ruby/2.2.0/rubygems/core_ext/kernel_require.rb:54:in `require' -e:1:in `<main>' Tasks: TOP => db:setup => db:seed
I am stumped here. I thought by deleting the old table and running the new generate commands + migrating everything would be in order. Apparently this is not the case.
What am I doing wrong here?
edited to include line 45 of my seeds.rb
Comment.create!(
-
infused almost 9 yearsThe error is raised on line 45 of your seeds.rb file. What's on that line?
-
Jonathan Musso almost 9 yearsI edited my post to include that line which is "Comment.create!(
-
Florent Ferry almost 9 yearsYou don't add
user_id
tocomment
. But you addcommed_id
touser
. Socomment
have nouser_id
column. You should migrateAddUserstoComment user_id:integer:index
.
-
-
max almost 9 yearsI totally missed that he had added the column to the wrong table (which you can see in the edit) - but I choose to salvage the answer.
-
Jonathan Musso almost 9 yearsI have deleted the files in the migration folder and the comment.rb model. If I run ActiveRecord::Base.connection.execute("drop table comments") will I be able to start fresh with your answer?
-
max almost 9 yearsYou can run
rake db:reset
instead. It will drop the database and then runrake db:setup
. -
Jonathan Musso almost 9 yearsWhen I try rake db:reset I get this error: ActiveRecord::UnknownAttributeError: unknown attribute 'user' for Comment.
-
max almost 9 yearsTry splitting it up:
rake db:drop
,rake:db:migrate
- make sure the migration is successful. Then runrake db:seed
. -
Jonathan Musso almost 9 yearsThe drop appeared to work, no console output? Migration fails with SQLite3::SQLException: duplicate column name: user_id: ALTER TABLE "comments" ADD "user_id" integer/Users/jon/code/bloccit/db/migrate/20150508170603_add_users_to_comment.rb:3:in `change' so I must change the add_reference :user to :user_id?
-
max almost 9 yearsLet us continue this discussion in chat.