Factorygirl has_one通过模型联系

时间:2013-01-30 12:52:48

标签: ruby-on-rails testing rspec factory-bot

我的模型与has_one关联through另一个模型。

class Publisher
  has_many :books
end

class Book
  belongs_to :publisher
  has_one :author
end

class Author
  belongs_to :book
  has_one :publisher, :through => :book
end

在我的Rails代码中,我可以毫无问题地调用author.publisher,这样一切正常。但是在我的规格中(使用Rspec和FactoryGirl,这种关联似乎不起作用。这是我的FactoryGirl定义:

Factory.define :author do |a|
  a.association :book
end

Factory.define :book do |b|
  b.association :publisher
end

Factory.define :publisher
end

(忽略了工厂的大部分属性)。

现在在我的规格中,我可以执行以下操作

pub = Factory(:publisher)
book = Factory(:book, :publisher => pub)
author = Factory(:author, :book => book)

author.book # => Returns book
author.book.publisher # => Returns publisher 
author.publisher # => nil

那么我的through协会为何不起作用?

1 个答案:

答案 0 :(得分:2)

factory_girl / factory_girl_rails 4.1.0中,以下内容适用于我:

<强> factories.rb

FactoryGirl.define do

  factory :author do
    book
  end

  factory :book do
    publisher
  end

  factory :publisher do
  end

end

在rails控制台中:

pub = FactoryGirl.create(:publisher)
#=> #<Publisher id: 1, created_at: "2013-01-30 13:35:26", updated_at: "2013-01-30 13:35:26">
book = FactoryGirl.create(:book, :publisher => pub)
#=> #<Book id: 1, publisher_id: 1, created_at: "2013-01-30 13:36:23", updated_at: "2013-01-30 13:36:23">
author = FactoryGirl.create(:author, :book => book)
#=> #<Author id: 1, book_id: 1, created_at: "2013-01-30 13:36:57", updated_at: "2013-01-30 13:36:57">
author.book
#=> #<Book id: 1, publisher_id: 1, created_at: "2013-01-30 13:36:23", updated_at: "2013-01-30 13:36:23">
author.book.publisher
#=> #<Publisher id: 1, created_at: "2013-01-30 13:35:26", updated_at: "2013-01-30 13:35:26">
author.publisher
#=> #<Publisher id: 1, created_at: "2013-01-30 13:35:26", updated_at: "2013-01-30 13:35:26">

奇怪的是,最后author.publisher需要额外的SELECT操作,而author.book.publisher则不需要(可能与您观察到的nil相关):

Publisher Load (0.2ms)  SELECT "publishers".* FROM "publishers"
  INNER JOIN "books" ON "publishers"."id" = "books"."publisher_id"
  WHERE "books"."id" = 1 LIMIT 1

如果你使用Publisher.createBook.createAuthor.create代替FactoryGirl.create,会发生同样的事情,所以这不是工厂女孩的行为,而是铁路行为,与此有关如何缓存through个关联。