Class: Factory

Inherits:
Object
  • Object
show all
Defined in:
lib/factory_girl/aliases.rb,
lib/factory_girl/factory.rb,
lib/factory_girl/sequence.rb,
lib/factory_girl/attribute.rb,
lib/factory_girl/attribute_proxy.rb

Defined Under Namespace

Classes: Attribute, AttributeDefinitionError, AttributeProxy, Sequence

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(name, options = {}) ⇒ Factory

:nodoc:



38
39
40
41
42
43
# File 'lib/factory_girl/factory.rb', line 38

def initialize (name, options = {}) #:nodoc:
  options.assert_valid_keys(:class)
  @factory_name = factory_name_for(name)
  @options      = options
  @attributes   = []
end

Dynamic Method Handling

This class handles dynamic methods through the method_missing method

#method_missing(name, *args, &block) ⇒ Object

Calls add_attribute using the missing method name as the name of the attribute, so that:

Factory.define :user do |f|
  f.name 'Billy Idol'
end

and:

Factory.define :user do |f|
  f.add_attribute :name, 'Billy Idol'
end

are equivilent.



103
104
105
# File 'lib/factory_girl/factory.rb', line 103

def method_missing (name, *args, &block)
  add_attribute(name, *args, &block)
end

Instance Attribute Details

#factory_nameObject (readonly)

Returns the value of attribute factory_name.



13
14
15
# File 'lib/factory_girl/factory.rb', line 13

def factory_name
  @factory_name
end

Class Method Details

.alias(pattern, replace) ⇒ Object

Defines a new alias for attributes

Arguments:

pattern: (Regexp)
  A pattern that will be matched against attributes when looking for
  aliases. Contents captured in the pattern can be used in the alias.
replace: (String)
  The alias that results from the matched pattern. Captured strings can
  be insert like String#sub.

Example:

Factory.alias /(.*)_confirmation/, '\1'


22
23
24
# File 'lib/factory_girl/aliases.rb', line 22

def self.alias (pattern, replace)
  self.aliases << [pattern, replace]
end

.aliases_for(attribute) ⇒ Object

:nodoc:



26
27
28
29
30
31
32
33
34
35
# File 'lib/factory_girl/aliases.rb', line 26

def self.aliases_for (attribute) #:nodoc:
  aliases.collect do |params|
    pattern, replace = *params
    if pattern.match(attribute.to_s)
      attribute.to_s.sub(pattern, replace).to_sym
    else
      nil
    end
  end.compact << attribute
end

.attributes_for(name, attrs = {}) ⇒ Object

Generates and returns a Hash of attributes from this factory. Attributes can be individually overridden by passing in a Hash of attribute => value pairs.

Arguments:

attrs: (Hash)
  Attributes to overwrite for this set.

Returns:

A set of attributes that can be used to build an instance of the class
this factory generates. (Hash)


163
164
165
# File 'lib/factory_girl/factory.rb', line 163

def attributes_for (name, attrs = {})
  factory_by_name(name).attributes_for(attrs)
end

.build(name, attrs = {}) ⇒ Object

Generates and returns an instance from this factory. Attributes can be individually overridden by passing in a Hash of attribute => value pairs.

Arguments:

attrs: (Hash)
  See attributes_for

Returns:

An instance of the class this factory generates, with generated
attributes assigned.


177
178
179
# File 'lib/factory_girl/factory.rb', line 177

def build (name, attrs = {})
  factory_by_name(name).build(attrs)
end

.create(name, attrs = {}) ⇒ Object

Generates, saves, and returns an instance from this factory. Attributes can be individually overridden by passing in a Hash of attribute => value pairs.

If the instance is not valid, an ActiveRecord::Invalid exception will be raised.

Arguments:

attrs: (Hash)
  See attributes_for

Returns:

A saved instance of the class this factory generates, with generated
attributes assigned.


195
196
197
# File 'lib/factory_girl/factory.rb', line 195

def create (name, attrs = {})
  factory_by_name(name).create(attrs)
end

.define(name, options = {}) {|instance| ... } ⇒ Object

Defines a new factory that can be used by the build strategies (create and build) to build new objects.

Arguments:

name: (Symbol)
  A unique name used to identify this factory.
options: (Hash)
  class: the class that will be used when generating instances for this
         factory. If not specified, the class will be guessed from the 
         factory name.

Yields:

The newly created factory (Factory)

Yields:

  • (instance)


28
29
30
31
32
# File 'lib/factory_girl/factory.rb', line 28

def self.define (name, options = {})
  instance = Factory.new(name, options)
  yield(instance)
  self.factories[instance.factory_name] = instance
end

.find_definitionsObject

:nodoc:



199
200
201
202
203
204
205
206
207
# File 'lib/factory_girl/factory.rb', line 199

def find_definitions #:nodoc:
  definition_file_paths.each do |path|
    begin
      require(path)
      break
    rescue LoadError
    end
  end
end

.next(sequence) ⇒ Object

Generates and returns the next value in a sequence.

Arguments:

name: (Symbol)
  The name of the sequence that a value should be generated for.

Returns:

The next value in the sequence. (Object)


48
49
50
51
52
53
54
# File 'lib/factory_girl/sequence.rb', line 48

def self.next (sequence)
  unless self.sequences.key?(sequence)
    raise "No such sequence: #{sequence}"
  end

  self.sequences[sequence].next
end

.sequence(name, &block) ⇒ Object

Defines a new sequence that can be used to generate unique values in a specific format.

Arguments:

name: (Symbol)
  A unique name for this sequence. This name will be referenced when
  calling next to generate new values from this sequence.
block: (Proc)
  The code to generate each value in the sequence. This block will be
  called with a unique number each time a value in the sequence is to be
  generated. The block should return the generated value for the
  sequence.

Example:

Factory.sequence(:email) {|n| "somebody_#{n}@example.com" }


36
37
38
# File 'lib/factory_girl/sequence.rb', line 36

def self.sequence (name, &block)
  self.sequences[name] = Sequence.new(&block)
end

Instance Method Details

#add_attribute(name, value = nil, &block) ⇒ Object

Adds an attribute that should be assigned on generated instances for this factory.

This method should be called with either a value or block, but not both. If called with a block, the attribute will be generated “lazily,” whenever an instance is generated. Lazy attribute blocks will not be called if that attribute is overriden for a specific instance.

When defining lazy attributes, an instance of Factory::AttributeProxy will be yielded, allowing associations to be built using the correct build strategy.

Arguments:

name: (Symbol)
  The name of this attribute. This will be assigned using :"#{name}=" for
  generated instances.
value: (Object)
  If no block is given, this value will be used for this attribute.


63
64
65
66
67
68
69
70
71
# File 'lib/factory_girl/factory.rb', line 63

def add_attribute (name, value = nil, &block)
  attribute = Attribute.new(name, value, block)

  if attribute_defined?(attribute.name)
    raise AttributeDefinitionError, "Attribute already defined: #{name}"
  end

  @attributes << attribute
end

#association(name, options = {}) ⇒ Object

Adds an attribute that builds an association. The associated instance will be built using the same build strategy as the parent instance.

Example:

Factory.define :user do |f|
  f.name 'Joey'
end

Factory.define :post do |f|
  f.association :author, :factory => :user
end

Arguments:

name: (Symbol)
  The name of this attribute.
options: (Hash)
  factory: (Symbol)
    The name of the factory to use when building the associated instance.
    If no name is given, the name of the attribute is assumed to be the
    name of the factory. For example, a "user" association will by
    default use the "user" factory.


128
129
130
131
132
133
134
# File 'lib/factory_girl/factory.rb', line 128

def association (name, options = {})
  name    = name.to_sym
  options = options.symbolize_keys
  association_factory = options[:factory] || name

  add_attribute(name) {|a| a.association(association_factory) }
end

#attributes_for(attrs = {}) ⇒ Object

:nodoc:



136
137
138
# File 'lib/factory_girl/factory.rb', line 136

def attributes_for (attrs = {}) #:nodoc:
  build_attributes_hash(attrs, :attributes_for)
end

#build(attrs = {}) ⇒ Object

:nodoc:



140
141
142
# File 'lib/factory_girl/factory.rb', line 140

def build (attrs = {}) #:nodoc:
  build_instance(attrs, :build)
end

#build_classObject

:nodoc:



34
35
36
# File 'lib/factory_girl/factory.rb', line 34

def build_class #:nodoc:
  @build_class ||= class_for(@options[:class] || factory_name)
end

#create(attrs = {}) ⇒ Object

:nodoc:



144
145
146
147
148
# File 'lib/factory_girl/factory.rb', line 144

def create (attrs = {}) #:nodoc:
  instance = build_instance(attrs, :create)
  instance.save!
  instance
end

#sequence(name, &proc) ⇒ Object

Adds an anonymous sequence for an attribute:

Factory.define :user do |f|
  f.sequence do |n|
    "Johnny #{n}"
  end
end

When generating an instance, the next value in the sequence will be used.



82
83
84
85
86
87
# File 'lib/factory_girl/factory.rb', line 82

def sequence (name, &proc)
  sequence = Sequence.new(&proc)
  add_attribute(name) do
    sequence.next
  end
end