Permalink
Browse files

Introduce declarations

Declarations are another layer of abstraction between defining the
factories via the DSL and compiling the factories and their attributes.

Declarations know how to return their attribute(s), and running a
factory compiles the declarations before building all attributes on the
factory. This moves all the attribute compilation logic into one
centralized location on the Factory instance, which means traits (and
potentially other features down the road) can have individual attributes
overridden within child factories or through FactoryGirl.modify

Closes #205
  • Loading branch information...
1 parent 306e51b commit a154e64da18fc282d9437c136c17972faf7c1d58 Joe Ferris and Josh Clayton committed with joshuaclayton Sep 23, 2011
View
22 GETTING_STARTED.md
@@ -379,6 +379,24 @@ the trait that defines the attribute latest gets precedence.
factory :female_admin, :traits => [:admin, :female] # login will be "Jane Doe (F)"
end
+You can also override individual attributes granted by a trait in subclasses.
+
+ factory :user do
+ name "Friendly User"
+ login { name }
+
+ trait :male do
+ name "John Doe"
+ gender "Male"
+ login { "#{name} (M)" }
+ end
+
+ factory :brandon do
+ male
+ name "Brandon"
+ end
+ end
+
Callbacks
---------
@@ -457,10 +475,8 @@ When modifying a factory, you can change any of the attributes you want (aside f
`FactoryGirl.modify` must be called outside of a `FactoryGirl.define` block as it operates on factories differently.
-A couple caveats: you can only modify factories (not sequences or traits) and callbacks *still compound as they normally would*. So, if
+A caveat: you can only modify factories (not sequences or traits) and callbacks *still compound as they normally would*. So, if
the factory you're modifying defines an `after_create` callback, you defining an `after_create` won't override it, it'll just get run after the first callback.
-You also can't modify attributes assigned by traits. So, if you have a trait that grants a name attribute, and you modify the factory to set the name,
-it currently will reflect the name in the trait instead of the modified name.
Building or Creating Multiple Records
-------------------------------------
View
7 lib/factory_girl.rb
@@ -10,9 +10,12 @@
require 'factory_girl/attribute/dynamic'
require 'factory_girl/attribute/association'
require 'factory_girl/attribute/sequence'
-require 'factory_girl/attribute/implicit'
-require 'factory_girl/attribute/trait'
require 'factory_girl/callback'
+require 'factory_girl/declaration'
+require 'factory_girl/declaration/static'
+require 'factory_girl/declaration/dynamic'
+require 'factory_girl/declaration/association'
+require 'factory_girl/declaration/implicit'
require 'factory_girl/sequence'
require 'factory_girl/attribute_list'
require 'factory_girl/trait'
View
37 lib/factory_girl/attribute/implicit.rb
@@ -1,37 +0,0 @@
-module FactoryGirl
- class Attribute
-
- class Implicit < Attribute
- def initialize(name, factory = nil)
- super(name)
- @factory = factory
- end
-
- def add_to(proxy)
- implementation.add_to(proxy)
- end
-
- def association?
- implementation.association?
- end
-
- def factory
- name
- end
-
- private
-
- def implementation
- @implementation ||=
- if FactoryGirl.factories.registered?(name)
- Attribute::Association.new(name, name, {})
- elsif FactoryGirl.sequences.registered?(name)
- Attribute::Sequence.new(name, name)
- else
- Attribute::Trait.new(name, @factory)
- end
- end
- end
-
- end
-end
View
8 lib/factory_girl/attribute/static.rb
@@ -3,6 +3,8 @@ class Attribute #:nodoc:
class Static < Attribute #:nodoc:
+ attr_reader :value
+
def initialize(name, value)
super(name)
@value = value
@@ -15,6 +17,12 @@ def add_to(proxy)
def priority
0
end
+
+ def ==(another)
+ self.name == another.name &&
+ self.value == another.value &&
+ self.ignored == another.ignored
+ end
end
end
end
View
22 lib/factory_girl/attribute/trait.rb
@@ -1,22 +0,0 @@
-module FactoryGirl
- class Attribute #:nodoc:
-
- class Trait < Attribute #:nodoc:
- def initialize(name, factory)
- super(name)
- @factory = factory
- end
-
- def add_to(proxy)
- trait.attributes.each { |attr| attr.add_to(proxy) }
- end
-
- private
-
- def trait
- (@factory || FactoryGirl).trait_by_name(name)
- end
- end
-
- end
-end
View
7 lib/factory_girl/attribute_list.rb
@@ -2,14 +2,19 @@ module FactoryGirl
class AttributeList
include Enumerable
- attr_reader :callbacks
+ attr_reader :callbacks, :declarations
def initialize
@attributes = {}
+ @declarations = []
@overridable = false
@callbacks = []
end
+ def declare_attribute(declaration)
+ @declarations << declaration
+ end
+
def define_attribute(attribute)
if !overridable? && attribute_defined?(attribute.name)
raise AttributeDefinitionError, "Attribute already defined: #{attribute.name}"
View
19 lib/factory_girl/declaration.rb
@@ -0,0 +1,19 @@
+module FactoryGirl
+ class Declaration
+ attr_reader :name
+
+ def initialize(name)
+ @name = name
+ end
+
+ def ignore
+ @ignored = true
+ end
+
+ def to_attributes
+ build.tap do |attributes|
+ attributes.each(&:ignore) if @ignored
+ end
+ end
+ end
+end
View
17 lib/factory_girl/declaration/association.rb
@@ -0,0 +1,17 @@
+module FactoryGirl
+ class Declaration
+ class Association < Declaration
+ def initialize(name, options)
+ super(name)
+ @options = options
+ end
+
+ private
+
+ def build
+ factory_name = @options.delete(:factory) || name
+ [Attribute::Association.new(name, factory_name, @options)]
+ end
+ end
+ end
+end
View
16 lib/factory_girl/declaration/dynamic.rb
@@ -0,0 +1,16 @@
+module FactoryGirl
+ class Declaration
+ class Dynamic < Declaration
+ def initialize(name, block)
+ super(name)
+ @block = block
+ end
+
+ private
+
+ def build
+ [Attribute::Dynamic.new(name, @block)]
+ end
+ end
+ end
+end
View
23 lib/factory_girl/declaration/implicit.rb
@@ -0,0 +1,23 @@
+module FactoryGirl
+ class Declaration
+ class Implicit < Declaration
+ def initialize(name, factory = nil)
+ super(name)
+ @factory = factory
+ end
+
+ private
+
+ def build
+ if FactoryGirl.factories.registered?(name)
+ [Attribute::Association.new(name, name, {})]
+ elsif FactoryGirl.sequences.registered?(name)
+ [Attribute::Sequence.new(name, name)]
+ else
+ trait_root = @factory || FactoryGirl
+ trait_root.trait_by_name(name).attributes.to_a
+ end
+ end
+ end
+ end
+end
View
16 lib/factory_girl/declaration/static.rb
@@ -0,0 +1,16 @@
+module FactoryGirl
+ class Declaration
+ class Static < Declaration
+ def initialize(name, value)
+ super(name)
+ @value = value
+ end
+
+ private
+
+ def build
+ [Attribute::Static.new(name, @value)]
+ end
+ end
+ end
+end
View
12 lib/factory_girl/definition_proxy.rb
@@ -36,13 +36,14 @@ def add_attribute(name, value = nil, &block)
if value
raise AttributeDefinitionError, "Both value and block given"
else
- attribute = Attribute::Dynamic.new(name, block)
+ declaration = Declaration::Dynamic.new(name, block)
end
else
- attribute = Attribute::Static.new(name, value)
+ declaration = FactoryGirl::Declaration::Static.new(name, value)
end
- @factory.define_attribute(attribute)
+ @factory.declare_attribute(declaration)
+ declaration
end
# Calls add_attribute using the missing method name as the name of the
@@ -78,7 +79,7 @@ def add_attribute(name, value = nil, &block)
# are equivalent.
def method_missing(name, *args, &block)
if args.empty? && block.nil?
- @factory.define_attribute(Attribute::Implicit.new(name, @factory))
+ @factory.declare_attribute(Declaration::Implicit.new(name, @factory))
elsif args.first.is_a?(Hash) && args.first.has_key?(:factory)
association(name, *args)
else
@@ -131,8 +132,7 @@ def sequence(name, start_value = 1, &block)
# name of the factory. For example, a "user" association will by
# default use the "user" factory.
def association(name, options = {})
- factory_name = options.delete(:factory) || name
- @factory.define_attribute(Attribute::Association.new(name, factory_name, options))
+ @factory.declare_attribute(Declaration::Association.new(name, options))
end
def after_build(&block)
View
83 lib/factory_girl/factory.rb
@@ -13,7 +13,6 @@ class DuplicateDefinitionError < RuntimeError
class Factory
attr_reader :name #:nodoc:
- attr_reader :traits #:nodoc:
def factory_name
puts "WARNING: factory.factory_name is deprecated. Use factory.name instead."
@@ -34,69 +33,61 @@ def default_strategy #:nodoc:
def initialize(name, options = {}) #:nodoc:
assert_valid_options(options)
- @name = factory_name_for(name)
- @parent = options[:parent]
- @options = options
- @traits = []
- @children = []
- @attribute_list = AttributeList.new
- @inherited_attribute_list = AttributeList.new
+ @name = factory_name_for(name)
+ @parent = options[:parent]
+ @parent_factory = nil
+ @options = options
+ @defined_traits = []
+ @traits = []
+ @children = []
+ @attribute_list = AttributeList.new
+ @compiled = false
end
def allow_overrides
@attribute_list.overridable
- @inherited_attribute_list.overridable
self
end
def allow_overrides?
@attribute_list.overridable?
end
- def inherit_from(parent) #:nodoc:
+ def inherit_factory(parent) #:nodoc:
@options[:class] ||= parent.class_name
@options[:default_strategy] ||= parent.default_strategy
allow_overrides if parent.allow_overrides?
parent.add_child(self)
- @inherited_attribute_list.apply_attributes(parent.attributes)
+ @parent_factory = parent
end
def add_child(factory)
@children << factory unless @children.include?(factory)
end
- def apply_traits(traits) #:nodoc:
- traits.reverse.map { |name| trait_by_name(name) }.each do |trait|
- apply_attributes(trait.attributes)
- end
- end
-
- def apply_attributes(attributes_to_apply)
- @attribute_list.apply_attributes(attributes_to_apply)
- end
-
- def define_attribute(attribute)
- if attribute.respond_to?(:factory) && attribute.factory == self.name
- raise AssociationDefinitionError, "Self-referencing association '#{attribute.name}' in factory '#{self.name}'"
- end
-
- @attribute_list.define_attribute(attribute).tap { update_children }
+ def inherit_traits(traits)
+ @traits = traits
end
def define_trait(trait)
- @traits << trait
+ @defined_traits << trait
end
def add_callback(name, &block)
@attribute_list.add_callback(Callback.new(name, block))
end
def attributes
+ ensure_compiled
AttributeList.new.tap do |list|
+ @traits.reverse.map { |name| trait_by_name(name) }.each do |trait|
+ list.apply_attributes(trait.attributes)
+ end
+
list.apply_attributes(@attribute_list)
- list.apply_attributes(@inherited_attribute_list)
+ list.apply_attributes(@parent_factory.attributes) if @parent_factory
end
end
@@ -172,10 +163,36 @@ def callbacks
attributes.callbacks
end
+ def compile
+ declarations.each do |declaration|
+ declaration.to_attributes.each do |attribute|
+ define_attribute(attribute)
+ end
+ end
+ @compiled = true
+ end
+
+ def declare_attribute(declaration)
+ @attribute_list.declare_attribute(declaration)
+ end
+
private
+ def declarations
+ @attribute_list.declarations
+ end
+
def update_children
- @children.each { |child| child.inherit_from(self) }
+ @children.each { |child| child.inherit_factory(self) }
+ end
+
+ def define_attribute(attribute)
+ if attribute.respond_to?(:factory) && attribute.factory == self.name
+ raise AssociationDefinitionError, "Self-referencing association '#{attribute.name}' in factory '#{self.name}'"
+ end
+
+ @attribute_list.define_attribute(attribute)
+ update_children if allow_overrides?
end
def class_for (class_or_to_s)
@@ -240,7 +257,11 @@ def symbolize_keys(hash)
end
def trait_for(name)
- traits.detect {|trait| trait.name == name }
+ @defined_traits.detect {|trait| trait.name == name }
+ end
+
+ def ensure_compiled
+ compile unless @compiled
end
end
end
View
6 lib/factory_girl/syntax/default.rb
@@ -22,12 +22,13 @@ def factory(name, options = {}, &block)
proxy.instance_eval(&block) if block_given?
if traits = options.delete(:traits)
- factory.apply_traits(traits)
+ factory.inherit_traits(traits)
end
if parent = options.delete(:parent)
- factory.inherit_from(FactoryGirl.factory_by_name(parent))
+ factory.inherit_factory(FactoryGirl.factory_by_name(parent))
end
+
FactoryGirl.register_factory(factory)
proxy.child_factories.each do |(child_name, child_options, child_block)|
@@ -53,6 +54,7 @@ def factory(name, options = {}, &block)
factory = FactoryGirl.factory_by_name(name).allow_overrides
proxy = FactoryGirl::DefinitionProxy.new(factory)
proxy.instance_eval(&block)
+ factory.compile
end
end
end
View
14 lib/factory_girl/trait.rb
@@ -10,16 +10,24 @@ def initialize(name, &block) #:nodoc:
proxy.instance_eval(&block) if block_given?
end
- def define_attribute(attribute)
- @attribute_list.define_attribute(attribute)
+ def declare_attribute(declaration)
+ @attribute_list.declare_attribute(declaration)
+ declaration
end
def add_callback(name, &block)
@attribute_list.add_callback(Callback.new(name, block))
end
def attributes
- @attribute_list
+ AttributeList.new.tap do |list|
+ @attribute_list.declarations.each do |declaration|
+ declaration.to_attributes.each do |attribute|
+ list.define_attribute(attribute)
+ end
+ end
+ list.apply_attributes @attribute_list
+ end
end
def names
View
52 spec/acceptance/modify_inherited_spec.rb
@@ -0,0 +1,52 @@
+require "spec_helper"
+
+describe "modifying inherited factories with traits" do
+ before do
+ define_model('User', :gender => :string, :admin => :boolean, :age => :integer)
+ FactoryGirl.define do
+ factory :user do
+ trait(:female) { gender "Female" }
+ trait(:male) { gender "Male" }
+
+ trait(:young_admin) do
+ admin true
+ age 17
+ end
+
+ female
+ young_admin
+
+ factory :female_user do
+ gender "Female"
+ age 25
+ end
+
+ factory :male_user do
+ gender "Male"
+ end
+ end
+ end
+ end
+
+ it "returns the correct value for overridden attributes from traits" do
+ Factory.build(:male_user).gender.should == "Male"
+ end
+
+ it "returns the correct value for overridden attributes from traits defining multiple attributes" do
+ Factory.build(:female_user).gender.should == "Female"
+ Factory.build(:female_user).age.should == 25
+ Factory.build(:female_user).admin.should == true
+ end
+
+ it "allows modification of attributes created via traits" do
+ FactoryGirl.modify do
+ factory :male_user do
+ age 20
+ end
+ end
+
+ Factory.build(:male_user).gender.should == "Male"
+ Factory.build(:male_user).age.should == 20
+ Factory.build(:male_user).admin.should == true
+ end
+end
View
8 spec/acceptance/syntax/vintage_spec.rb
@@ -46,13 +46,7 @@
end
end
-describe Factory, "given a parent factory" do
- before do
- @parent = FactoryGirl::Factory.new(:object)
- @parent.define_attribute(FactoryGirl::Attribute::Static.new(:name, 'value'))
- FactoryGirl.register_factory(@parent)
- end
-
+describe Factory, "referencing a nonexistent factory as a parent" do
it "should raise an ArgumentError when trying to use a non-existent factory as parent" do
lambda {
Factory.define(:child, :parent => :nonexsitent) {}
View
27 spec/factory_girl/attribute/implicit_spec.rb → ...factory_girl/declaration/implicit_spec.rb
@@ -1,24 +1,27 @@
require 'spec_helper'
-describe FactoryGirl::Attribute::Implicit do
- let(:name) { :author }
- let(:proxy) { stub("proxy") }
- subject { FactoryGirl::Attribute::Implicit.new(name) }
-
- its(:name) { should == name }
+describe FactoryGirl::Declaration::Implicit do
+ let(:name) { :author }
+ let(:proxy) { stub("proxy") }
+ subject { FactoryGirl::Declaration::Implicit.new(name) }
+ let(:attribute) { subject.to_attributes.first }
context "with a known factory" do
before do
FactoryGirl.factories.stubs(:registered? => true)
end
- it { should be_association }
+ it "generates an association" do
+ attribute.should be_association
+ end
- its(:factory) { should == name }
+ it "generates an association with the correct factory" do
+ attribute.factory.should == name
+ end
it "associates the factory" do
proxy.stubs(:associate)
- subject.add_to(proxy)
+ attribute.add_to(proxy)
proxy.should have_received(:associate).with(name, name, {})
end
end
@@ -27,11 +30,13 @@
let(:sequence) { FactoryGirl::Sequence.new(name, 1) { "magic" } }
before { FactoryGirl.register_sequence(sequence) }
- it { should_not be_association }
+ it "doesn't generate an association" do
+ attribute.should_not be_association
+ end
it "generates the sequence" do
proxy.stubs(:set)
- subject.add_to(proxy)
+ attribute.add_to(proxy)
proxy.should have_received(:set).with(name, "magic")
end
end
View
28 spec/factory_girl/definition_proxy_spec.rb
@@ -4,21 +4,26 @@
let(:factory) { FactoryGirl::Factory.new(:object) }
subject { FactoryGirl::DefinitionProxy.new(factory) }
+ def attributes
+ factory.attributes
+ end
+
it "should add a static attribute for type" do
subject.type 'value'
- factory.attributes.to_a.last.should be_kind_of(FactoryGirl::Attribute::Static)
+ attributes.to_a.last.should be_kind_of(FactoryGirl::Attribute::Static)
end
it "should add a static attribute for id" do
subject.id 'value'
- factory.attributes.to_a.last.should be_kind_of(FactoryGirl::Attribute::Static)
+ attributes.to_a.last.should be_kind_of(FactoryGirl::Attribute::Static)
end
it "should add a static attribute when an attribute is defined with a value" do
attribute = stub('attribute', :name => :name)
FactoryGirl::Attribute::Static.stubs(:new => attribute)
factory.stubs(:define_attribute)
subject.add_attribute(:name, 'value')
+ factory.compile
factory.should have_received(:define_attribute).with(attribute)
FactoryGirl::Attribute::Static.should have_received(:new).with(:name, "value")
end
@@ -29,6 +34,7 @@
FactoryGirl::Attribute::Dynamic.stubs(:new => attribute)
factory.stubs(:define_attribute)
subject.add_attribute(:name, &block)
+ factory.compile
FactoryGirl::Attribute::Dynamic.should have_received(:new).with(:name, block)
factory.should have_received(:define_attribute).with(attribute)
end
@@ -41,7 +47,7 @@
it "should add an attribute with a built-in private method" do
subject.instance_eval { sleep(0.1) }
- factory.attributes.map { |attribute| attribute.name }.should == [:sleep]
+ attributes.map { |attribute| attribute.name }.should == [:sleep]
end
describe "child factories" do
@@ -67,15 +73,6 @@
FactoryGirl::Sequence.should have_received(:new).with(:name, "A")
end
end
-
- it "adds an implicit attribute when passed an undefined method without arguments or a block" do
- factory.stubs(:define_attribute)
- attribute = stub('attribute', :name => :name)
- FactoryGirl::Attribute::Implicit.stubs(:new => attribute)
- subject.send(:name)
- FactoryGirl::Attribute::Implicit.should have_received(:new).with(:name, factory)
- factory.should have_received(:define_attribute).with(attribute)
- end
end
describe FactoryGirl::DefinitionProxy, "with a factory mock" do
@@ -126,12 +123,14 @@ def to_create(&block)
it "creates a dynamic attribute" do
subject.add_attribute(attribute_name, &block)
+ factory.compile
FactoryGirl::Attribute::Dynamic.should have_received(:new).with(attribute_name, block)
factory.should have_received(:define_attribute).with(attribute)
end
it "creates a dynamic attribute without the method being defined" do
subject.send(attribute_name, &block)
+ factory.compile
FactoryGirl::Attribute::Dynamic.should have_received(:new).with(attribute_name, block)
factory.should have_received(:define_attribute).with(attribute)
end
@@ -142,12 +141,14 @@ def to_create(&block)
it "creates a static attribute" do
subject.add_attribute(attribute_name, attribute_value)
+ factory.compile
FactoryGirl::Attribute::Static.should have_received(:new).with(attribute_name, attribute_value)
factory.should have_received(:define_attribute).with(attribute)
end
it "creates a static attribute without the method being defined" do
subject.send(attribute_name, attribute_value)
+ factory.compile
FactoryGirl::Attribute::Static.should have_received(:new).with(attribute_name, attribute_value)
factory.should have_received(:define_attribute).with(attribute)
end
@@ -179,13 +180,15 @@ def to_create(&block)
it "defines an association attribute with the factory name" do
subject.association(association_name, options)
+ factory.compile
factory.should have_received(:define_attribute).with(attribute)
FactoryGirl::Attribute::Association.should have_received(:new).with(association_name, factory_name, :name => "John Doe")
end
it "defines an association attribute when the association is called implicitly" do
subject.send(association_name, options)
+ factory.compile
factory.should have_received(:define_attribute).with(attribute)
FactoryGirl::Attribute::Association.should have_received(:new).with(association_name, factory_name, :name => "John Doe")
@@ -197,6 +200,7 @@ def to_create(&block)
it "defines an association attribute with the association name" do
subject.association(association_name, options)
+ factory.compile
factory.should have_received(:define_attribute).with(attribute)
FactoryGirl::Attribute::Association.should have_received(:new).with(association_name, association_name, options)
View
76 spec/factory_girl/factory_spec.rb
@@ -38,9 +38,9 @@
it "should return associations" do
factory = FactoryGirl::Factory.new(:post)
FactoryGirl.register_factory(FactoryGirl::Factory.new(:admin))
- factory.define_attribute(FactoryGirl::Attribute::Association.new(:author, :author, {}))
- factory.define_attribute(FactoryGirl::Attribute::Association.new(:editor, :editor, {}))
- factory.define_attribute(FactoryGirl::Attribute::Implicit.new(:admin))
+ factory.declare_attribute(FactoryGirl::Declaration::Association.new(:author, {}))
+ factory.declare_attribute(FactoryGirl::Declaration::Association.new(:editor, {}))
+ factory.declare_attribute(FactoryGirl::Declaration::Implicit.new(:admin, factory))
factory.associations.each do |association|
association.should be_association
end
@@ -50,7 +50,8 @@
it "should raise for a self referencing association" do
factory = FactoryGirl::Factory.new(:post)
lambda {
- factory.define_attribute(FactoryGirl::Attribute::Association.new(:parent, :post, {}))
+ factory.declare_attribute(FactoryGirl::Declaration::Association.new(:parent, { :factory => :post }))
+ factory.attributes
}.should raise_error(FactoryGirl::AssociationDefinitionError)
end
@@ -62,21 +63,21 @@
end
it "should return the overridden value in the generated attributes" do
- attr = FactoryGirl::Attribute::Static.new(@name, 'The price is wrong, Bob!')
- @factory.define_attribute(attr)
+ declaration = FactoryGirl::Declaration::Static.new(@name, 'The price is wrong, Bob!')
+ @factory.declare_attribute(declaration)
result = @factory.run(FactoryGirl::Proxy::AttributesFor, @hash)
result[@name].should == @value
end
it "should not call a lazy attribute block for an overridden attribute" do
- attr = FactoryGirl::Attribute::Dynamic.new(@name, lambda { flunk })
- @factory.define_attribute(attr)
+ declaration = FactoryGirl::Declaration::Dynamic.new(@name, lambda { flunk })
+ @factory.declare_attribute(declaration)
result = @factory.run(FactoryGirl::Proxy::AttributesFor, @hash)
end
it "should override a symbol parameter with a string parameter" do
- attr = FactoryGirl::Attribute::Static.new(@name, 'The price is wrong, Bob!')
- @factory.define_attribute(attr)
+ declaration = FactoryGirl::Declaration::Static.new(@name, 'The price is wrong, Bob!')
+ @factory.declare_attribute(declaration)
@hash = { @name.to_s => @value }
result = @factory.run(FactoryGirl::Proxy::AttributesFor, @hash)
result[@name].should == @value
@@ -85,7 +86,7 @@
describe "overriding an attribute with an alias" do
before do
- @factory.define_attribute(FactoryGirl::Attribute::Static.new(:test, 'original'))
+ @factory.declare_attribute(FactoryGirl::Declaration::Static.new(:test, 'original'))
Factory.alias(/(.*)_alias/, '\1')
@result = @factory.run(FactoryGirl::Proxy::AttributesFor,
:test_alias => 'new')
@@ -106,52 +107,52 @@
it "should create a new factory using the class of the parent" do
child = FactoryGirl::Factory.new(:child)
- child.inherit_from(@factory)
+ child.inherit_factory(@factory)
child.build_class.should == @factory.build_class
end
it "should create a new factory while overriding the parent class" do
child = FactoryGirl::Factory.new(:child, :class => String)
- child.inherit_from(@factory)
+ child.inherit_factory(@factory)
child.build_class.should == String
end
describe "given a parent with attributes" do
before do
@parent_attr = :name
- @factory.define_attribute(FactoryGirl::Attribute::Static.new(@parent_attr, 'value'))
+ @factory.declare_attribute(FactoryGirl::Declaration::Static.new(@parent_attr, 'value'))
end
it "should create a new factory with attributes of the parent" do
child = FactoryGirl::Factory.new(:child)
- child.inherit_from(@factory)
+ child.inherit_factory(@factory)
child.attributes.size.should == 1
child.attributes.first.name.should == @parent_attr
end
it "should allow a child to define additional attributes" do
child = FactoryGirl::Factory.new(:child)
- child.define_attribute(FactoryGirl::Attribute::Static.new(:email, 'value'))
- child.inherit_from(@factory)
+ child.declare_attribute(FactoryGirl::Declaration::Static.new(:email, 'value'))
+ child.inherit_factory(@factory)
child.attributes.size.should == 2
end
it "should allow to override parent attributes" do
child = FactoryGirl::Factory.new(:child)
- @child_attr = FactoryGirl::Attribute::Static.new(@parent_attr, 'value')
- child.define_attribute(@child_attr)
- child.inherit_from(@factory)
+ @child_declaration = FactoryGirl::Declaration::Static.new(@parent_attr, 'overridden')
+ child.declare_attribute(@child_declaration)
+ child.inherit_factory(@factory)
child.attributes.size.should == 1
- child.attributes.first.should == @child_attr
+ child.attributes.first.should == @child_declaration.to_attributes.first
end
it "should allow to use parent attributes in defining additional attributes" do
User.class_eval { attr_accessor :name, :email }
child = FactoryGirl::Factory.new(:child)
- @child_attr = FactoryGirl::Attribute::Dynamic.new(:email, lambda {|u| "#{u.name}@example.com"})
- child.define_attribute(@child_attr)
- child.inherit_from(@factory)
+ @child_declaration = FactoryGirl::Declaration::Dynamic.new(:email, lambda {|u| "#{u.name}@example.com"})
+ child.declare_attribute(@child_declaration)
+ child.inherit_factory(@factory)
child.attributes.size.should == 2
result = child.run(FactoryGirl::Proxy::Build, {})
@@ -162,9 +163,14 @@
it "inherits callbacks" do
@factory.add_callback(:after_stub) { |object| object.name = 'Stubby' }
child = FactoryGirl::Factory.new(:child)
- child.inherit_from(@factory)
+ child.inherit_factory(@factory)
child.callbacks.should_not be_empty
end
+
+ it "compiles when looking for attributes" do
+ @factory.declare_attribute(FactoryGirl::Declaration::Static.new("name", "value"))
+ @factory.attributes.size.should == 1
+ end
end
describe FactoryGirl::Factory, "when defined with a custom class" do
@@ -265,7 +271,7 @@
subject { factory_without_strategy }
before do
- subject.inherit_from(parent)
+ subject.inherit_factory(parent)
end
it "inherits default strategy from its parent" do
@@ -278,7 +284,7 @@
subject { factory_with_build_strategy }
before do
- subject.inherit_from(parent)
+ subject.inherit_factory(parent)
end
it "overrides the default strategy from parent" do
@@ -308,16 +314,20 @@
end
describe FactoryGirl::Factory, "running a factory" do
- subject { FactoryGirl::Factory.new(:user) }
- let(:attribute) { FactoryGirl::Attribute::Static.new(:name, "value") }
- let(:proxy) { stub("proxy", :result => "result", :set => nil) }
+ subject { FactoryGirl::Factory.new(:user) }
+ let(:attribute) { FactoryGirl::Attribute::Static.new(:name, "value") }
+ let(:declaration) { FactoryGirl::Declaration::Static.new(:name, "value") }
+ let(:proxy) { stub("proxy", :result => "result", :set => nil) }
+ let(:attributes) { [attribute] }
+ let(:attribute_list) { stub('attribute-list', :declarations => [declaration], :to_a => attributes) }
before do
define_model("User", :name => :string)
- FactoryGirl::Attribute::Static.stubs(:new => attribute)
- FactoryGirl::Proxy::Build.stubs(:new => proxy)
- subject.define_attribute(attribute)
+ FactoryGirl::Declaration::Static.stubs(:new => declaration)
+ declaration.stubs(:to_attributes => attributes)
attribute.stubs(:add_to => nil)
+ FactoryGirl::Proxy::Build.stubs(:new => proxy)
+ subject.declare_attribute(declaration)
end
it "creates the right proxy using the build class when running" do

0 comments on commit a154e64

Please sign in to comment.