Class: FluentFixtures::Factory
- Inherits:
-
Object
- Object
- FluentFixtures::Factory
- Extended by:
- Loggability
- Includes:
- Enumerable
- Defined in:
- lib/fluent_fixtures/factory.rb
Overview
The fluent fixture monadic factory class.
Constant Summary collapse
- CREATE_METHODS =
The methods to look for to save new instances when #create is called
%i[ save_changes save ]
- DEFAULT_GENERATOR_LIMIT =
The default limit for generators
10_000
Instance Attribute Summary collapse
-
#constructor_args ⇒ Object
readonly
The Array of arguments to pass to the constructor when creating a new fixtured object.
-
#constructor_block ⇒ Object
readonly
The block to pass to the constructor when creating a new fixtured object.
-
#decorators ⇒ Object
readonly
The decorators that will be applied to the fixtured object when it’s created.
-
#fixture_module ⇒ Object
readonly
The fixture module that contains the decorator declarations.
Instance Method Summary collapse
-
#create(args = {}, &block) ⇒ Object
Return a saved #instance of the fixtured object.
-
#decorated_with(&block) ⇒ Object
Return a copy of the factory that will apply the specified
block
as a decorator. -
#each(&block) ⇒ Object
Iterate over DEFAULT_GENERATOR_LIMIT instances of the fixtured object, yielding each new instance if a block is provided.
-
#generator(create: false, limit: DEFAULT_GENERATOR_LIMIT, &block) ⇒ Object
Return an infinite generator for unsaved instances of the fixtured object.
-
#initialize(fixture_module, *args, &block) ⇒ Factory
constructor
Create a new FluentFactory that will act as a monadic factory for the specified
fixture_module
, and use the givenargs
in the construction of new objects. -
#initialize_copy(original) ⇒ Object
Copy constructor – make a distinct copy of the clone’s decorators.
-
#inspect ⇒ Object
Return a human-readable representation of the object suitable for debugging.
-
#instance(args = {}, &block) ⇒ Object
Create an instance, apply declared decorators in order, and return the resulting object.
-
#mutate(name, *args, &block) ⇒ Object
Return a new clone of the receiver with an additional decorator composed of the specified
name
,args
, andblock
.
Constructor Details
#initialize(fixture_module, *args, &block) ⇒ Factory
Create a new FluentFactory that will act as a monadic factory for the specified fixture_module
, and use the given args
in the construction of new objects.
27 28 29 30 31 32 |
# File 'lib/fluent_fixtures/factory.rb', line 27 def initialize( fixture_module, *args, &block ) @fixture_module = fixture_module @constructor_args = args @constructor_block = block @decorators = [] end |
Dynamic Method Handling
This class handles dynamic methods through the method_missing method
#method_missing(sym, *args, &block) ⇒ Object (protected)
Proxy method – look up the decorator with the same name as the method being called, and if one is found, returned a new instance of the factory with the additional decorator.
280 281 282 |
# File 'lib/fluent_fixtures/factory.rb', line 280 def method_missing( sym, *args, &block ) return self.mutate( sym, *args, &block ) end |
Instance Attribute Details
#constructor_args ⇒ Object (readonly)
The Array of arguments to pass to the constructor when creating a new fixtured object.
51 52 53 |
# File 'lib/fluent_fixtures/factory.rb', line 51 def constructor_args @constructor_args end |
#constructor_block ⇒ Object (readonly)
The block to pass to the constructor when creating a new fixtured object.
55 56 57 |
# File 'lib/fluent_fixtures/factory.rb', line 55 def constructor_block @constructor_block end |
#decorators ⇒ Object (readonly)
The decorators that will be applied to the fixtured object when it’s created.
47 48 49 |
# File 'lib/fluent_fixtures/factory.rb', line 47 def decorators @decorators end |
#fixture_module ⇒ Object (readonly)
The fixture module that contains the decorator declarations
43 44 45 |
# File 'lib/fluent_fixtures/factory.rb', line 43 def fixture_module @fixture_module end |
Instance Method Details
#create(args = {}, &block) ⇒ Object
Return a saved #instance of the fixtured object.
105 106 107 108 109 110 111 112 113 |
# File 'lib/fluent_fixtures/factory.rb', line 105 def create( args={}, &block ) obj = self.with_transaction do obj = self.instance( args, &block ) obj = self.try_to_save( obj ) obj end return obj end |
#decorated_with(&block) ⇒ Object
Return a copy of the factory that will apply the specified block
as a decorator.
117 118 119 |
# File 'lib/fluent_fixtures/factory.rb', line 117 def decorated_with( &block ) return self.mutate( nil, &block ) end |
#each(&block) ⇒ Object
Iterate over DEFAULT_GENERATOR_LIMIT instances of the fixtured object, yielding each new instance if a block is provided. If no block is provided, returns an Enumerator.
125 126 127 128 |
# File 'lib/fluent_fixtures/factory.rb', line 125 def each( &block ) return self.generator unless block return self.generator.each( &block ) end |
#generator(create: false, limit: DEFAULT_GENERATOR_LIMIT, &block) ⇒ Object
Return an infinite generator for unsaved instances of the fixtured object.
132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 |
# File 'lib/fluent_fixtures/factory.rb', line 132 def generator( create: false, limit: DEFAULT_GENERATOR_LIMIT, &block ) return Enumerator.new( limit || Float::INFINITY ) do |yielder| count = 0 constructor = create ? :create : :instance loop do break if limit && count >= limit obj = if block self.send( constructor, &block.curry(2)[count] ) else self.send( constructor ) end yielder.yield( obj ) count += 1 end end end |
#initialize_copy(original) ⇒ Object
Copy constructor – make a distinct copy of the clone’s decorators.
36 37 38 |
# File 'lib/fluent_fixtures/factory.rb', line 36 def initialize_copy( original ) @decorators = @decorators.dup end |
#inspect ⇒ Object
Return a human-readable representation of the object suitable for debugging.
154 155 156 157 158 159 160 161 162 163 |
# File 'lib/fluent_fixtures/factory.rb', line 154 def inspect decorator_description = self.decorators.map( &:first ).join( ' + ' ) return "#<%p:%0#16x for %p%s>" % [ self.class, self.__id__ * 2, self.fixture_module, decorator_description.empty? ? '' : ' + ' + decorator_description ] end |
#instance(args = {}, &block) ⇒ Object
Create an instance, apply declared decorators in order, and return the resulting object.
69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 |
# File 'lib/fluent_fixtures/factory.rb', line 69 def instance( args={}, &block ) instance = self.fixture_module. fixtured_instance( *self.constructor_args, &self.constructor_block ) self.decorators.each do |decorator_name, decorator_args, block| # :TODO: Reify other fixtures in `decorator_args` here? if !decorator_name self.apply_inline_decorator( instance, block ) elsif self.fixture_module.decorators.key?( decorator_name ) instance = self.apply_named_decorator( instance, decorator_args, decorator_name ) else self.apply_method_decorator( instance, decorator_args, decorator_name, block ) end end args.each_pair do |attrname, value| # :TODO: Reify the `value` if it responds to #create? instance.public_send( "#{attrname}=", value ) end # If the factory was called with a block, use it as a final decorator before # returning it. if block self.log.debug "Applying inline decorator %p" % [ block ] if block.arity.zero? instance.instance_exec( &block ) else block.call( instance ) end end return instance end |
#mutate(name, *args, &block) ⇒ Object
Return a new clone of the receiver with an additional decorator composed of the specified name
, args
, and block
.
60 61 62 63 64 |
# File 'lib/fluent_fixtures/factory.rb', line 60 def mutate( name, *args, &block ) new_instance = self.dup new_instance.decorators << [ name, args, block ] return new_instance end |