【问题标题】:Failed to create nested attribute in Factory Girl?在 Factory Girl 中创建嵌套属性失败?
【发布时间】:2012-11-12 08:29:23
【问题描述】:

我在PostCategory 模型之间有一个many-to-many 关联:

categorization.rb:

class Categorization < ActiveRecord::Base
  attr_accessible :category_id, :post_id, :position

  belongs_to :post
  belongs_to :category
end

category.rb:

class Category < ActiveRecord::Base
  attr_accessible :name

  has_many :categorizations
  has_many :posts, :through => :categorizations  

  validates :name, presence: true, length: { maximum: 14 }
end

post.rb:

class Post < ActiveRecord::Base
  attr_accessible :title, :content, :category_ids

  has_many :categorizations
  has_many :categories, :through => :categorizations  

  accepts_nested_attributes_for :categorizations, allow_destroy: true

end

这行得通:

post_spec.rb:

describe Post do

  let(:user) { FactoryGirl.create(:user) }
  let(:category) { FactoryGirl.create(:category) }
  before { @post = user.posts.build(title: "Lorem ipsum",
                                    content: "Lorem ipsum dolor sit amet",
                                    category_ids: category) }

我的问题就在这里:

factories.rb:

  factory :post do
    title "Lorem"
    content "Lorem ipsum"
    category_ids category
    user
  end

  factory :category do
    name "Lorem"
  end

reply_spec.rb:

describe Reply do

  let(:post) { FactoryGirl.create(:post) }
  let(:reply) { post.replies.build(content: "Lorem ipsum dolor sit amet") }

当我为reply_spec.rb 运行测试时,我收到了这个错误:

> undefined method `category=' for #<Post:0x9e07564>

我认为这是不起作用的部分:

factories.rb:

  category_ids category

我是否以错误的方式定义了嵌套属性?什么是正确的?

【问题讨论】:

  • 查看此链接factory girl,也许正是您需要的。
  • @Kien Thanh 谢谢,我认为它有一些有用的概念,但我认为它是针对has_and_belongs_to_many 关联的。不是我在这里使用的:many =&gt; through

标签: ruby-on-rails factory-bot


【解决方案1】:

这篇文章使用 after_build 钩子来创建关联:Populating an association with children in factory_girl

我个人喜欢不要让工厂过于复杂(使它们在 imo 中过于具体),而是根据需要在测试中实例化任何必要的关联。

factories.rb:

factory :post do
  title "Lorem"
  content "Lorem ipsum"
  user
end

factory :category do
  name "Lorem"
end

post_spec.rb:

...
let(:post) {FactoryGirl.create(:post, :category => FactoryGirl.create(:category))}

(编辑——因为 post 对象与分类相关联,而不是直接与类别相关联)

let(:post) {FactoryGirl.create(:post)}
let(:categorization) {FactoryGirl.create(:categorization, 
                                  :post=> post, 
                                  :category=> FactoryGirl.create(:category))}

【讨论】:

  • 谢谢,您的代码稍作修改即可工作:let(:post) {FactoryGirl.create(:post, :category_ids =&gt; FactoryGirl.create(:category))} 但是该代码在factories.rb 中会是什么样子?
  • 文档说:只是category 将适用于工厂定义......我认为更好的做法是始终在测试中实例化关联,而不是制作复杂的工厂。 (你冒着让你的测试过于专业化的风险,imo)。
  • 感谢您的回答。对不起,我对此很陌生,你能给我一个实例化这个关联的例子吗? (我意识到仅仅向 post factory 添加类别是行不通的,因为它是一个many-to-many 关联)。
  • 我在帖子中添加了一个编辑,因为帖子与分类关联而不是直接与类别关联,这可能会造成混淆。我更喜欢保持工厂定义简单,并在测试期间创建关联。希望这是有道理的——我刚开始时对 ruby​​ 测试感到非常困惑,这绝对是一门学科,但你学得越多就越有意义!​​
  • 谢谢,但我认为我遇到了验证错误:Validation failed: Tag ids can't be blank 我在帖子中有 tag_ids 必填字段。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2011-03-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-02-16
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多