根据我的理解,工厂''to_create'方法的返回值将被忽略。这意味着从工厂的'build'或'initialize_with'部分返回的对象是在测试中调用'create'时最终返回的对象。
就我而言,我使用的是存储库模式的变体。我正在覆盖工厂的'to_create'部分,以包含对存储库'save'方法的调用。此方法不会修改给定对象,但会返回表示原始持久形式的对象。
但是,从'build'块返回的实例是从工厂返回的,而不是在'to_create'块中创建的实例。在我的代码中,这意味着返回对象的“未加载”形式,而不是保存操作中具有更新属性(例如“id”)的对象。
有没有办法强制'create'的返回值是'to_create'块的结果还是在该块中生成的某个值?
class Foo
attr_accessor :id, :name
...
end
class FooRepository
def self.create(name)
Foo.new(name) # this object is not yet persisted and has no .id
end
def self.save(foo)
# this method must not guarantee that the original Foo instance
# will always be returned
...
updated_foo # this is a duplicate of the original object
end
...
end
FactoryGirl.define do
factory :foo, class: FooRepository do
# create an example Foo
initialize_with { FooRepository.create(name: "Example") }
# save the Foo to the datastore, returning what may be a duplicate
to_create {|instance| FooRepository.save(instance)}
end
end
describe FooRepository do
it "saves the given Foo to the datastore" do
foo = create(:foo)
foo.id #=> nil
...
end
end
答案 0 :(得分:4)
除了“raise an issue”之外,我没有给你答案,对不起。
默认的to_create回调如下所示:
$ grep to_create lib/factory_girl/configuration.rb
to_create {|instance| instance.save! }
主要问题是当您在其上调用save!
时,ActiveRecord会自行修改。 FactoryGirl将忽略从to_create
返回的所有新对象。
如果要覆盖默认创建策略,请快速入侵:
module FactoryGirl
module Strategy
class Create
def association(runner)
runner.run
end
def result(evaluation)
evaluation.object.tap do |instance|
evaluation.notify(:after_build, instance)
evaluation.notify(:before_create, instance)
instance = evaluation.create(instance) # <-- HACK
evaluation.notify(:after_create, instance)
end
end
end
end
end
...或者对你的to_create
钩子进行模仿Rails的就地修改:
to_create do |record|
new_record = YourRepositoryHere.new.create(record)
record.attributes = new_record.attributes # For example
new_record # Return the record just in case the bug is fixed
end
祝你好运。 :(