2013-09-01 23 views
5

Dalla mia comprensione, il valore restituito dal metodo "to_create" di una factory viene ignorato. Ciò significa che l'oggetto restituito dalla parte 'build' o 'initialize_with' della factory è l'oggetto restituito alla fine quando si chiama 'create' all'interno di un test.FactoryGirl to_create valore restituito

Nel mio caso, sto usando una variante del modello di deposito. Sto sovrascrivendo la parte 'to_create' della factory per includere una chiamata al metodo 'save' del repository. Questo metodo non modifica l'oggetto dato, ma restituisce un oggetto che rappresenta la forma persistente dell'originale.

Tuttavia, l'istanza restituita dal blocco 'build' viene restituita dalla fabbrica e non l'istanza creata nel blocco 'to_create'. Nel mio codice, questo significa che viene restituita la forma "non protetta" dell'oggetto, non l'oggetto con attributi aggiornati (ad esempio "id") dall'azione di salvataggio.

Esiste un modo per forzare il valore restituito di 'create' come risultato del blocco 'to_create' o di qualche valore generato all'interno di quel blocco?

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 

risposta

4

Non ho una risposta per voi oltre "raise an issue", mi spiace.

callback to_create

L'impostazione di default è simile al seguente:

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

Il problema principale è che ActiveRecord si modifica in atto quando si chiama save! su di esso. FactoryGirl ignorerà qualsiasi nuovo oggetto restituito da to_create.

Un hack rapido se si vuole ignorare l'impostazione predefinita creare strategia:

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 

... O fare questo per il vostro gancio to_create per imitare Rails' sul posto modifica:

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 

Buona fortuna. :(

+0

Nice! Ha aiutato con qualche problema diverso, ma comunque una bella risposta! :) – Aleks