ActiveModel::MissingAttributeError: 无法写入未知属性 `user_id` [英] ActiveModel::MissingAttributeError: can't write unknown attribute `user_id`

查看:46
本文介绍了ActiveModel::MissingAttributeError: 无法写入未知属性 `user_id`的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试实施评论"作为我正在构建的项目的任务的一部分.

I am trying to implement a "comment" feature as part of my assignment for an project I am building.

在课程的早些时候,我们创建了一个评论表,并让 Faker gem 生成虚假评论.

Earlier in the course we created a comment table and had the Faker gem generate fake comments.

我的说明如下:

评论必须与用户相关联,因此在评论表中添加一个 user_id 外键.记得也要给它添加一个索引;

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;

更新 User 模型以便您可以调用 user.comments,并更新 Comment 模型以便您可以调用 comment.user;

Update the User model so you can call user.comments, and the Comment model so you can call comment.user;

修改seeds.rb文件,在运行db:reset时创建有效的注释;

Modify the seeds.rb file to create valid comments when you run db:reset;

最初我试图运行我的 rails generate 命令,但一直遇到这个错误:

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

它似乎起作用了.然后我就可以在终端中运行这些了.<​​/p>

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

迁移/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 时,我收到此错误.

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)

这是完整的堆栈跟踪:

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.

我在这里做错了什么?

编辑以包含我的种子文件的第 45 行

Comment.create!(

推荐答案

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

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

当然,如果应用程序尚未部署,您可以删除违规迁移并运行 rake db:reset

Of course if the App has not been deployed you could just delete the offending migration and run 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 一次性创建索引和外键.

add_reference creates a index and a foreign key in one sweep.

这篇关于ActiveModel::MissingAttributeError: 无法写入未知属性 `user_id`的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆