ActiveModel :: MissingAttributeError:无法使用FactoryGirl编写未知属性`ad_id'

52

我有以下模型:

class Ad < ActiveRecord::Base
  belongs_to :page

  has_one :image
  has_one :logo
end

class Page < ActiveRecord::Base
  has_many :logos
  has_many :images
  has_many :ads
end

class Image < ActiveRecord::Base
  belongs_to :page
  has_many :ads
end

我已经定义了以下工厂:

factory :page do
  url 'test.com'
end

factory :image do
  width 200
  height 200
  page
end

factory :ad do
  background 'rgb(255,0,0)'
  page
  image
end

当我尝试执行以下操作时:

ad = FactoryGirl.create(:ad) 我在广告工厂中决定图像关联的那一行代码上收到以下错误:ActiveModel :: MissingAttributeError:无法写入未知属性ad_id'

我做错了什么?


1
Mauricio,只是缺少工厂的属性,但我已经展示了它们的关联。无论如何,我已经添加了它们。 - Hommer Smith
6个回答

61

当您说:

has_one :image
Rails期望您在images表中定义一个ad_id字段。考虑到您的关联方式,我假设您在ads表中有一个image_idlogo_id,因此可以这样修改:
class Ad < ActiveRecord::Base
  belongs_to :page

  has_one :image
  has_one :logo
end

你可能是指:

class Ad < ActiveRecord::Base
  belongs_to :page
  belongs_to :image
  belongs_to :logo
end
如果不是这种情况,那么您需要在ImageLogo两个表中都添加ad_id列。

哦,那很有趣。我使用了“has_one”,因为说广告有一张图片听起来更自然。 - Hommer Smith
17
has_onehas_many 表示外键位于关联对象的另一端,而 belongs_to 表示外键位于当前对象。 - Maurício Linhares
8
belongs_tohas_onehas_many 在我看来并不是很描述底层数据库模式。referencesreferenced_by_onereferenced_by_many 更难被误解。 - Martin Gjaldbaek
3
对于那些说,“这个问题跟我的很相似,但我确定我的数据库架构是正确的”的人,请注意,您可能和我一样,只关注于开发而不是测试。请确保该字段在测试中已被迁移。(可以尝试类似于RAILS_ENV=test bundle exec rake db:migrate的命令,但具体情况可能有所不同。) - codenoob
2
我在 Stack Overflow 上读过一个好的记忆口诀,但现在找不到了。它是用“玩具总动员”法来记住关键字。安迪拥有木牛,木牛属于安迪。那么外键在哪里呢?在木牛的脚上! - Corbin
显示剩余2条评论

6

如果你在运行规范时出现此错误,可能是新添加的字段没有在测试环境中迁移。因此,请使用以下命令在测试环境中进行迁移。

rake db:migrate db:test:prepare

3
我遇到了同样的错误,花费了一些时间才找到解决方法。以防将来有人也会遇到这个问题,下面是我的情况和解决方法。由于这是工作上的事情,类名已更改:
我有两个命名空间模型:
Pantry::Jar
has_many :snacks, class_name: Pantry::Snack
accepts_nested_attributes_for :snacks

Pantry::Snack
belongs_to :pantry_jar, class_name: Pantry::Jar

当我创建一个新的罐子并放入新的零食时,我会得到:

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

修复方法是更明确地改变 has_many 的外键:
has_many :snacks, class_name: Pantry::Snack, foreign_key: :pantry_jar_id

2

请检查您的测试数据库。

在我的情况下,有时在错误迁移后,我没有修改测试数据库中的列,而是修改了开发数据库中的列。


2

如果您在测试过程中遇到错误,并且使用不同的存储库访问相同的测试数据库,请检查项目之间的迁移是否相等。

如果每次运行测试时都重置数据库,则仅运行该存储库中可用的迁移,因此会触发与缺少外键相关的错误。

ActiveModel::MissingAttributeError: can't write unknown attribute ad_id'

您应该有类似以下内容的迁移文件:
class AddAdReferenceToImage < ActiveRecord::Migration[5.0]
  def change
    add_reference :images, :ad, foreign_key: true
  end
end


0
在我的情况下,出现了这个消息是因为我尝试设置一个引用(列名与类名不同)如下:
Entity.create(reference: some_obj).save!

虽然我不确定问题的具体原因,但是我通过使用列名而不是引用名称来解决了它:

Entity.create(reference_id: some_obj.id).save!

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接