1
0
Fork 0
mirror of https://github.com/thoughtbot/factory_bot.git synced 2022-11-09 11:43:51 -05:00

Callbacks aren't attributes

This commit is contained in:
Joe Ferris 2011-09-16 16:06:32 -04:00
parent 67fc3bc8a9
commit 4d30663a5b
13 changed files with 70 additions and 88 deletions

View file

@ -9,10 +9,10 @@ require 'factory_girl/attribute'
require 'factory_girl/attribute/static' require 'factory_girl/attribute/static'
require 'factory_girl/attribute/dynamic' require 'factory_girl/attribute/dynamic'
require 'factory_girl/attribute/association' require 'factory_girl/attribute/association'
require 'factory_girl/attribute/callback'
require 'factory_girl/attribute/sequence' require 'factory_girl/attribute/sequence'
require 'factory_girl/attribute/implicit' require 'factory_girl/attribute/implicit'
require 'factory_girl/attribute/trait' require 'factory_girl/attribute/trait'
require 'factory_girl/callback'
require 'factory_girl/sequence' require 'factory_girl/sequence'
require 'factory_girl/attribute_list' require 'factory_girl/attribute_list'
require 'factory_girl/trait' require 'factory_girl/trait'

View file

@ -29,10 +29,6 @@ module FactoryGirl
false false
end end
def callback?
false
end
def priority def priority
1 1
end end

View file

@ -1,18 +0,0 @@
module FactoryGirl
class Attribute #:nodoc:
class Callback < Attribute #:nodoc:
def initialize(name, block)
@name = name.to_sym
@block = block
end
def add_to(proxy)
proxy.add_callback(name, @block)
end
def callback?
true
end
end
end
end

View file

@ -2,9 +2,12 @@ module FactoryGirl
class AttributeList class AttributeList
include Enumerable include Enumerable
attr_reader :callbacks
def initialize def initialize
@attributes = {} @attributes = {}
@overridable = false @overridable = false
@callbacks = []
end end
def define_attribute(attribute) def define_attribute(attribute)
@ -20,7 +23,7 @@ module FactoryGirl
raise InvalidCallbackNameError, "#{name} is not a valid callback name. Valid callback names are #{valid_callback_names.inspect}" raise InvalidCallbackNameError, "#{name} is not a valid callback name. Valid callback names are #{valid_callback_names.inspect}"
end end
add_attribute Attribute::Callback.new(name.to_sym, block) @callbacks << Callback.new(name.to_sym, block)
end end
def each(&block) def each(&block)
@ -32,6 +35,7 @@ module FactoryGirl
end end
def apply_attributes(attributes_to_apply) def apply_attributes(attributes_to_apply)
attributes_to_apply.callbacks.each { |callback| add_callback(callback.name, &callback.block) }
new_attributes = [] new_attributes = []
attributes_to_apply.each do |attribute| attributes_to_apply.each do |attribute|
@ -56,6 +60,10 @@ module FactoryGirl
@overridable @overridable
end end
def size
to_a.size
end
private private
def valid_callback_names def valid_callback_names
@ -85,7 +93,7 @@ module FactoryGirl
end end
def find_attribute(attribute_name) def find_attribute(attribute_name)
@attributes.values.flatten.reject(&:callback?).detect do |attribute| @attributes.values.flatten.detect do |attribute|
attribute.name == attribute_name attribute.name == attribute_name
end end
end end

View file

@ -0,0 +1,10 @@
module FactoryGirl
class Callback
attr_reader :name, :block
def initialize(name, block)
@name = name.to_sym
@block = block
end
end
end

View file

@ -97,11 +97,12 @@ module FactoryGirl
AttributeList.new.tap do |list| AttributeList.new.tap do |list|
list.apply_attributes(@attribute_list) list.apply_attributes(@attribute_list)
list.apply_attributes(@inherited_attribute_list) list.apply_attributes(@inherited_attribute_list)
end.to_a end
end end
def run(proxy_class, overrides) #:nodoc: def run(proxy_class, overrides) #:nodoc:
proxy = proxy_class.new(build_class) proxy = proxy_class.new(build_class)
callbacks.each { |callback| proxy.add_callback(callback.name, callback.block) }
overrides = symbolize_keys(overrides) overrides = symbolize_keys(overrides)
attributes.each do |attribute| attributes.each do |attribute|
@ -167,6 +168,10 @@ module FactoryGirl
@to_create_block = block @to_create_block = block
end end
def callbacks
attributes.callbacks
end
private private
def update_children def update_children

View file

@ -19,7 +19,7 @@ module FactoryGirl
end end
def attributes def attributes
@attribute_list.to_a @attribute_list
end end
def names def names

View file

@ -1,24 +0,0 @@
require 'spec_helper'
describe FactoryGirl::Attribute::Callback do
let(:name) { :after_create }
let(:block) { proc { "block" } }
let(:proxy) { stub("proxy") }
subject { FactoryGirl::Attribute::Callback.new(name, block) }
its(:name) { should == name }
it { should be_callback }
it "set its callback on a proxy" do
proxy.stubs(:add_callback)
subject.add_to(proxy)
proxy.should have_received(:add_callback).with(name, block)
end
end
describe FactoryGirl::Attribute::Callback, "with a string name" do
subject { FactoryGirl::Attribute::Callback.new("name", nil) }
its(:name) { should == :name }
end

View file

@ -47,7 +47,7 @@ end
describe FactoryGirl::AttributeList, "#attribute_defined?" do describe FactoryGirl::AttributeList, "#attribute_defined?" do
let(:static_attribute) { FactoryGirl::Attribute::Static.new(:full_name, "value") } let(:static_attribute) { FactoryGirl::Attribute::Static.new(:full_name, "value") }
let(:callback_attribute) { FactoryGirl::Attribute::Callback.new(:after_create, lambda { }) } let(:callback_attribute) { FactoryGirl::Callback.new(:after_create, lambda { }) }
let(:static_attribute_named_after_create) { FactoryGirl::Attribute::Static.new(:after_create, "funky!") } let(:static_attribute_named_after_create) { FactoryGirl::Attribute::Static.new(:after_create, "funky!") }
it "knows if an attribute has been defined" do it "knows if an attribute has been defined" do
@ -58,15 +58,6 @@ describe FactoryGirl::AttributeList, "#attribute_defined?" do
subject.attribute_defined?(static_attribute.name).should == true subject.attribute_defined?(static_attribute.name).should == true
subject.attribute_defined?(:undefined_attribute).should == false subject.attribute_defined?(:undefined_attribute).should == false
end end
it "doesn't reference callbacks" do
subject.define_attribute(callback_attribute)
subject.attribute_defined?(:after_create).should == false
subject.define_attribute(static_attribute_named_after_create)
subject.attribute_defined?(:after_create).should == true
end
end end
describe FactoryGirl::AttributeList, "#add_callback" do describe FactoryGirl::AttributeList, "#add_callback" do
@ -78,14 +69,8 @@ describe FactoryGirl::AttributeList, "#add_callback" do
it "allows for defining adding a callback" do it "allows for defining adding a callback" do
subject.add_callback(:after_create) { "Called after_create" } subject.add_callback(:after_create) { "Called after_create" }
subject.first.name.should == :after_create subject.callbacks.first.name.should == :after_create
subject.callbacks.first.block.call.should == "Called after_create"
subject.first.add_to(proxy)
proxy.callbacks[:after_create].first.call.should == "Called after_create"
end
it "returns the callback" do
subject.add_callback(:after_create) { "Called after_create" }.should be_a(FactoryGirl::Attribute::Callback)
end end
it "allows valid callback names to be assigned" do it "allows valid callback names to be assigned" do
@ -111,22 +96,28 @@ describe FactoryGirl::AttributeList, "#apply_attributes" do
let(:email_attribute) { FactoryGirl::Attribute::Dynamic.new(:email, lambda {|model| "#{model.full_name}@example.com" }) } let(:email_attribute) { FactoryGirl::Attribute::Dynamic.new(:email, lambda {|model| "#{model.full_name}@example.com" }) }
let(:login_attribute) { FactoryGirl::Attribute::Dynamic.new(:login, lambda {|model| "username-#{model.full_name}" }) } let(:login_attribute) { FactoryGirl::Attribute::Dynamic.new(:login, lambda {|model| "username-#{model.full_name}" }) }
def list(*attributes)
FactoryGirl::AttributeList.new.tap do |list|
attributes.each { |attribute| list.define_attribute(attribute) }
end
end
it "prepends applied attributes" do it "prepends applied attributes" do
subject.define_attribute(full_name_attribute) subject.define_attribute(full_name_attribute)
subject.apply_attributes([city_attribute]) subject.apply_attributes(list(city_attribute))
subject.to_a.should == [city_attribute, full_name_attribute] subject.to_a.should == [city_attribute, full_name_attribute]
end end
it "moves non-static attributes to the end of the list" do it "moves non-static attributes to the end of the list" do
subject.define_attribute(full_name_attribute) subject.define_attribute(full_name_attribute)
subject.apply_attributes([city_attribute, email_attribute]) subject.apply_attributes(list(city_attribute, email_attribute))
subject.to_a.should == [city_attribute, full_name_attribute, email_attribute] subject.to_a.should == [city_attribute, full_name_attribute, email_attribute]
end end
it "maintains order of non-static attributes" do it "maintains order of non-static attributes" do
subject.define_attribute(full_name_attribute) subject.define_attribute(full_name_attribute)
subject.define_attribute(login_attribute) subject.define_attribute(login_attribute)
subject.apply_attributes([city_attribute, email_attribute]) subject.apply_attributes(list(city_attribute, email_attribute))
subject.to_a.should == [city_attribute, full_name_attribute, email_attribute, login_attribute] subject.to_a.should == [city_attribute, full_name_attribute, email_attribute, login_attribute]
end end
@ -134,7 +125,7 @@ describe FactoryGirl::AttributeList, "#apply_attributes" do
subject.define_attribute(full_name_attribute) subject.define_attribute(full_name_attribute)
attribute_with_same_name = FactoryGirl::Attribute::Static.new(:full_name, "Benjamin Franklin") attribute_with_same_name = FactoryGirl::Attribute::Static.new(:full_name, "Benjamin Franklin")
subject.apply_attributes([attribute_with_same_name]) subject.apply_attributes(list(attribute_with_same_name))
subject.to_a.should == [full_name_attribute] subject.to_a.should == [full_name_attribute]
end end
@ -143,20 +134,20 @@ describe FactoryGirl::AttributeList, "#apply_attributes" do
it "prepends applied attributes" do it "prepends applied attributes" do
subject.define_attribute(full_name_attribute) subject.define_attribute(full_name_attribute)
subject.apply_attributes([city_attribute]) subject.apply_attributes(list(city_attribute))
subject.to_a.should == [city_attribute, full_name_attribute] subject.to_a.should == [city_attribute, full_name_attribute]
end end
it "moves non-static attributes to the end of the list" do it "moves non-static attributes to the end of the list" do
subject.define_attribute(full_name_attribute) subject.define_attribute(full_name_attribute)
subject.apply_attributes([city_attribute, email_attribute]) subject.apply_attributes(list(city_attribute, email_attribute))
subject.to_a.should == [city_attribute, full_name_attribute, email_attribute] subject.to_a.should == [city_attribute, full_name_attribute, email_attribute]
end end
it "maintains order of non-static attributes" do it "maintains order of non-static attributes" do
subject.define_attribute(full_name_attribute) subject.define_attribute(full_name_attribute)
subject.define_attribute(login_attribute) subject.define_attribute(login_attribute)
subject.apply_attributes([city_attribute, email_attribute]) subject.apply_attributes(list(city_attribute, email_attribute))
subject.to_a.should == [city_attribute, full_name_attribute, email_attribute, login_attribute] subject.to_a.should == [city_attribute, full_name_attribute, email_attribute, login_attribute]
end end
@ -164,7 +155,7 @@ describe FactoryGirl::AttributeList, "#apply_attributes" do
subject.define_attribute(full_name_attribute) subject.define_attribute(full_name_attribute)
attribute_with_same_name = FactoryGirl::Attribute::Static.new(:full_name, "Benjamin Franklin") attribute_with_same_name = FactoryGirl::Attribute::Static.new(:full_name, "Benjamin Franklin")
subject.apply_attributes([attribute_with_same_name]) subject.apply_attributes(list(attribute_with_same_name))
subject.to_a.should == [attribute_with_same_name] subject.to_a.should == [attribute_with_same_name]
end end
end end

View file

@ -7,7 +7,6 @@ describe FactoryGirl::Attribute do
its(:name) { should == name.to_sym } its(:name) { should == name.to_sym }
it { should_not be_association } it { should_not be_association }
it { should_not be_callback }
it "doesn't set any attributes on a proxy when added" do it "doesn't set any attributes on a proxy when added" do
proxy.stubs(:set) proxy.stubs(:set)

View file

@ -0,0 +1,16 @@
require 'spec_helper'
describe FactoryGirl::Callback do
let(:name) { :after_create }
let(:block) { proc { "block" } }
let(:proxy) { stub("proxy") }
subject { FactoryGirl::Callback.new(name, block) }
its(:name) { should == name }
end
describe FactoryGirl::Callback, "with a string name" do
subject { FactoryGirl::Callback.new("name", nil) }
its(:name) { should == :name }
end

View file

@ -6,12 +6,12 @@ describe FactoryGirl::DefinitionProxy do
it "should add a static attribute for type" do it "should add a static attribute for type" do
subject.type 'value' subject.type 'value'
factory.attributes.last.should be_kind_of(FactoryGirl::Attribute::Static) factory.attributes.to_a.last.should be_kind_of(FactoryGirl::Attribute::Static)
end end
it "should add a static attribute for id" do it "should add a static attribute for id" do
subject.id 'value' subject.id 'value'
factory.attributes.last.should be_kind_of(FactoryGirl::Attribute::Static) factory.attributes.to_a.last.should be_kind_of(FactoryGirl::Attribute::Static)
end end
it "should add a static attribute when an attribute is defined with a value" do it "should add a static attribute when an attribute is defined with a value" do

View file

@ -159,11 +159,11 @@ describe FactoryGirl::Factory do
end end
end end
it "inherit all callbacks" do it "inherits callbacks" do
@factory.add_callback(:after_stub) { |object| object.name = 'Stubby' } @factory.add_callback(:after_stub) { |object| object.name = 'Stubby' }
child = FactoryGirl::Factory.new(:child) child = FactoryGirl::Factory.new(:child)
child.inherit_from(@factory) child.inherit_from(@factory)
child.attributes.last.should be_kind_of(FactoryGirl::Attribute::Callback) child.callbacks.should_not be_empty
end end
end end
@ -308,17 +308,16 @@ describe FactoryGirl::Factory, "human names" do
end end
describe FactoryGirl::Factory, "running a factory" do describe FactoryGirl::Factory, "running a factory" do
subject { FactoryGirl::Factory.new(:user) } subject { FactoryGirl::Factory.new(:user) }
let(:attribute) { stub("attribute", :name => :name, :ignored => false, :add_to => nil, :aliases_for? => true) } let(:attribute) { FactoryGirl::Attribute::Static.new(:name, "value") }
let(:attribute_list) { [attribute] } let(:proxy) { stub("proxy", :result => "result", :set => nil) }
let(:proxy) { stub("proxy", :result => "result", :set => nil) }
before do before do
define_model("User", :name => :string) define_model("User", :name => :string)
FactoryGirl::Attribute::Static.stubs(:new => attribute) FactoryGirl::Attribute::Static.stubs(:new => attribute)
FactoryGirl::Proxy::Build.stubs(:new => proxy) FactoryGirl::Proxy::Build.stubs(:new => proxy)
attribute_list.stubs(:apply_attributes) subject.define_attribute(attribute)
FactoryGirl::AttributeList.stubs(:new => attribute_list) attribute.stubs(:add_to => nil)
end end
it "creates the right proxy using the build class when running" do it "creates the right proxy using the build class when running" do