2013-09-01 8 views
5

私の理解から、工場の 'to_create'メソッドからの戻り値は無視されます。つまり、ファクトリの 'build'または 'initialize_with'部分から返されたオブジェクトは、テスト内で 'create'を呼び出すときに最終的に返されるオブジェクトです。FactoryGirl to_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 

答えて

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フックにこれを行う変更:

迅速なハックデフォルトの戦略を作成上書きする場合

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 

運が良かった。 :(

+0

ニース!それはいくつかの異なる問題を助けましたが、非常に素晴らしい答えです:) – Aleks