2013-09-01 14 views
5

Z mojego rozumowania, wartość zwracana z metody "to_create" fabryki jest ignorowana. Oznacza to, że obiekt zwrócony z części "build" lub "initialize_with" jest obiektem ostatecznie zwróconym podczas wywoływania "create" w teście.FactoryGirl to_create return value

W moim przypadku używam wariantu wzorca repozytorium. Nadpisuję część fabryki "to_create", aby dołączyć wywołanie metody składowania "repozytorium". Ta metoda nie modyfikuje podanego obiektu, ale zwraca obiekt reprezentujący utrwaloną formę oryginału.

Jednak instancja zwrócona z bloku "build" jest zwracana z fabryki, a nie z instancji utworzonej w bloku "to_create". W moim kodzie oznacza to, że zwracana jest "niezsobrana" forma obiektu, a nie obiekt ze zaktualizowanymi atrybutami (np. "Identyfikator") z akcji zapisywania.

Czy istnieje sposób na wymuszenie, aby wartość zwracana "create" była wynikiem bloku "to_create" lub wartości wygenerowanej w tym bloku?

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 

Odpowiedz

4

Nie mam dla ciebie odpowiedzi poza "raise an issue", przepraszam.

Domyślna to_create zwrotna wygląda następująco:

$ grep to_create lib/factory_girl/configuration.rb 
to_create {|instance| instance.save! } 

Głównym problemem jest to, że ActiveRecord modyfikuje się w miejscu podczas rozmowy save! na nim. FactoryGirl zignoruje wszelkie nowe obiekty zwrócone od to_create.

Szybkie hack, jeśli chcesz zastąpić domyślny tworzenia strategii:

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 

... Albo zrobić to do haka to_create naśladować Rails' w miejscu modyfikacji:

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 

Powodzenia. :(

+0

To mi pomogło z innym problemem, ale mimo to bardzo fajna odpowiedź! :) – Aleks