如何引用我在Fabricator中制作的对象?

dm7*_*m78 4 ruby ruby-on-rails fabrication-gem

我正在使用Ruby 2.1.1p76和Rails 4.0.4以及Fabrication gem.

是否可以参考目前正在制造的物体?

我有一个班级Foo和一个班级吧.我有每个制造商.我的问题是类Foo和Bar中的每一个都包含一个引用另一个类的字段:

class Foo < ActiveRecord::Base
  has_many :bars
  belongs_to :current_bar, class_name: "Bar"
end
Run Code Online (Sandbox Code Playgroud)

class Bar < ActiveRecord::Base
  belongs_to: :foo
end
Run Code Online (Sandbox Code Playgroud)

必须制作一个然后另一个然后在我的规范中为第一个设置参考是很麻烦的:

let!( :foo ) { Fabricate( :foo ) }
let!( :bar ) { Fabricate( :bar, foo: foo ) }

before( :each ) do
  foo.update( current_bar: bar )
end 
Run Code Online (Sandbox Code Playgroud)

我宁愿只是制作Foo和有其current_bar制造,并且已经提到我制造美孚.我已经阅读了制作宝石文档,我找不到任何可行的方法.我可能只是在忽视它.有谁知道这样做的方法?

为了完整性 - 制造商:

Fabricator( :foo ) do
  current_bar nil
end
Run Code Online (Sandbox Code Playgroud)

Fabricator( :bar ) do
  foo
end
Run Code Online (Sandbox Code Playgroud)

dm7*_*m78 6

对.在文档中忽略了它.


您可以在Fabricators中将它们定义为一个块,该块可选地接收正在制作的对象以及定义的任何瞬态属性的散列.与在Fabricator中工作的任何东西一样,您也可以在调用Fabricate时定义它们,它们将像您期望的那样工作.回调也可堆叠的,这意味着你可以在一个制造者声明相同类型的多个,当你继承另一个制造者,他们将不会被打一顿.

Fabricator(:place) do
  before_validation { |place, transients| place.geolocate! }
  after_create { |place, transients| Fabricate(:restaurant, place: place) }
end
Run Code Online (Sandbox Code Playgroud)

另外,在我的情况下,我需要使用after_save回调.我能够在制造商内部设置current_bar我的foo对象,但是一旦在规范中,它current_bar仍然是nil.updateafter_create里面没有这个方法(我是ruby的新手,所以我不知道为什么),但它在after_save中可用.调用更新让我走了.

Fabricator(:foo) do

  transient :current_bar_data

  after_save { |foo, transients|
    bar = Fabricate( :bar, foo: foo, bar_data: transients[ :current_bar_data ] )
    foo.update( current_bar: bar )
  }

  current_bar nil
end
Run Code Online (Sandbox Code Playgroud)

现在我可以为我的规格制作一个foo完整的current_bar:

let!( :some_foo ) { Fabricate( :foo, current_bar_data: "some bar data" ) }
Run Code Online (Sandbox Code Playgroud)