Why earlier: keep the callback hook without receiving a call from FactoryGirl.create ()?

This simple example uses the DataMapper callback before :save(aka hook) to increment callback_count. callback_count is initialized to 0 and must be set to 1 by a callback.

This callback is called when a TestObject is created using:

TestObject.create()

but the callback is skipped when creating FactoryGirl via:

FactoryGirl.create(:test_object)

Any idea why? [Note: I am running ruby ​​1.9.3, factory_girl 4.2.0, data_mapper 1.2.0]

Full information...

DataMapper Model

# file: models/test_model.rb
class TestModel
  include DataMapper::Resource

  property :id, Serial
  property :callback_count, Integer, :default => 0

  before :save do
    self.callback_count += 1
  end
end

FactoryGirl Announcement

# file: spec/factories.rb
FactoryGirl.define do
  factory :test_model do
  end
end

RSpec test

# file: spec/models/test_model_spec.rb
require 'spec_helper'

describe "TestModel Model" do
  it 'calls before :save using TestModel.create' do
    test_model = TestModel.create
    test_model.callback_count.should == 1
  end
  it 'fails to call before :save using FactoryGirl.create' do
    test_model = FactoryGirl.create(:test_model)
    test_model.callback_count.should == 1
  end
end

Test results

Failures:

  1) TestModel Model fails to call before :save using FactoryGirl.create
     Failure/Error: test_model.callback_count.should == 1
       expected: 1
            got: 0 (using ==)
     # ./spec/models/test_model_spec.rb:10:in `block (2 levels) in <top (required)>'

Finished in 0.00534 seconds
2 examples, 1 failure
+5
source share
3 answers

, factory_girl 4.2 ( , ), . Github, save save!.

FactoryGirl.define do
  to_create do |instance|
    if !instance.save
      raise "Save failed for #{instance.class}"
    end
  end
end

, , FactoryGirl, , , ...

, factory ( )

+3

.

@Jim Stewart FactoryGirl, : "FactoryGirl save! [ ]". DataMapper save! - , . ( , @enthrops!)

DataMapper, , , . , , Un-modified FactoryGirl DataMapper.

, . spec/factories.rb test_model_spec.rb . Cool beans.

# file: factories.rb
class CreateForDataMapper
  def initialize
    @default_strategy = FactoryGirl::Strategy::Create.new
  end

  delegate :association, to: :@default_strategy

  def result(evaluation)
    evaluation.singleton_class.send :define_method, :create do |instance|
      instance.save ||
        raise(instance.errors.send(:errors).map{|attr,errors| "- #{attr}: #{errors}"    }.join("\n"))
    end

    @default_strategy.result(evaluation)
  end
end

FactoryGirl.register_strategy(:create, CreateForDataMapper)

update 2

. , . CreateForDataMapper , , , . . - ?

+1

Use build to create your object, then call save manually ...

t = build(:test_model)
t.save
0
source

All Articles