ActiveModel::MissingAttributeError: can't write unknown attribute `user_id`

ActiveModel::MissingAttributeError: can't write unknown attribute `user_id`

我正在尝试实现一个“评论”功能,作为我正在构建的项目的任务的一部分。

在课程的早期,我们创建了一个评论 table 并让 Faker gem 生成虚假评论。

我的指令如下:

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;

最初我尝试 运行 我的 rails 生成命令但一直 运行ning 进入这个错误:

▶ 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)

所以我发现我需要从课程开始删除旧的 table。我在控制台中这样做了。

ActiveRecord::Base.connection.execute("drop table comments")

它似乎有效。然后我可以在终端中 运行 这些。

▶ 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

我的seeds.rb我变了

# 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

# Create Comments
50.times do 
  Comment.create!(
    user: users.sample,
    description: Faker::Lorem.paragraph
    )
end

现在当我 运行 rake db:reset 我得到这个错误。

▶ 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)

这是完整的堆栈跟踪:

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

我在这里被难住了。我想通过删除旧的 table 和 运行ning 新的生成命令 + 迁移所有内容就可以了。显然不是这样。

我做错了什么?

编辑以包含我的 seeds.rb

的第 45 行
Comment.create!(

您的迁移有误 - 您没有将 user_id 添加到 comments,而是添加了 users.commed

糟糕。它可能发生在我们最好的人身上。

所以首先让我们创建一个迁移来清除这个错误:

class RemoveCommedFromUsers < ActiveRecord::Migration
  def change
    remove_column :users, :commed # will also remove the index
  end
end

当然,如果应用程序尚未部署,您可以删除有问题的迁移和 运行 rake db:reset

所以让我们创建正确的迁移

rails g migration AddUserToComments user:belongs_to

生成以下迁移:

class AddUserToComments < ActiveRecord::Migration
  def change
    add_reference :comments, :user, index: true
  end
end

add_reference 一次性创建索引和外键。