Module: Mack::Data::Factory::ClassMethods

Defined in:
lib/mack-data_factory/data_factory.rb

Instance Method Summary collapse

Instance Method Details

#association(model_attrib_sym, assoc_map, assoc_rule = :spread) ⇒ Object

Define an association rule for this field.

Example:

class ItemFactory
  include Mack::Data::Factory
  ...
  association :owner_id, {:user => 'id'}, :random
end

The above example states that for each item generated, its owner_id will come from user’s id field. But which user? since the association rule is set to random, then the generator will pick random user.

Supported association rules:

:first:: If there are 10 users, then the item will get associated with user #0.
:last:: If there are 10 users, then the item will get associated with user #10.
:random:: If there are 10 users, then the item will get associated with user #rand(10)
:spread:: If there are 3 users, then the items' association will be spread out (i.e. 6 items will have id, sequentially, [0, 1, 2, 0, 1, 2])

Parameters:

model_attrib_sym: the name of the field
assoc_map: the association map


194
195
196
# File 'lib/mack-data_factory/data_factory.rb', line 194

def association(model_attrib_sym, assoc_map, assoc_rule = :spread)
  field(model_attrib_sym, {:default => {:df_assoc_map => assoc_map}, :assoc => assoc_rule})
end

#create(num, scope = :default) ⇒ Object

Run the factory to produce n number of objects.

Example:

class CarFactory
  include Mack::Data::Factory
  field(:name, :default => "honda") do |def_value, rules, index| 
    "#{def_value} #{['civic', 'accord', 'pilot'].randomize[0]}"
  end
end

CarFactory.create(100) #=> will produce 100 cars whose name is "honda xxx" where xxx is a random item from ['civic', 'accord', 'pilot']

Scoping:

In some instances, you may want different settings in the factory for different test scope.

You can achieve this by doing the following:

class UserFactory
    include Mack::Data::Factory

    field :username, :default => "planters", :length => 25, :content => :alpha
    field :password, :default => "roastedPeanuts", :immutable => true

    scope_for(:long_username) do
        field :username, :default => "planters", :length => 128, :content => :alpha
    end
end

The above example defined a scoping for “long_username”, which you can use by calling:

UserFactory.create(100, :long_username)

When a scope is defined and called, the field defined in the block will overwrite the default field listing in that class. Scopes in the factory is independent to each other, so one scope cannot affect the others.

Parameters:

num:  how many objects to produce
scope:  run the factory in a named scope.  By default the factory will be run in _default_ scope


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
102
103
104
105
106
107
108
109
110
111
# File 'lib/mack-data_factory/data_factory.rb', line 75

def create(num, scope = :default)
  factory_name = self.name.underscore
  
  # retrieve the model name from the factory class. 
  model_name = factory_name.gsub('_factory', '')
  
  # if user is running custom scope, then merge the fields 
  # defined for that scope with the default one, before we run the factory
  scoped_fields = field_manager.scopes[scope]
  fields = field_manager.scopes[:default].merge(scoped_fields)
  
  ret_arr = []
  
  Mack::Data::RegistryMap.reset!
  num.times do |i|
    #puts "Creating #{model_name} ##{i+1}"
    obj = model_name.camelcase.constantize.new
    
    fields.each_pair do |k, v|
      field_name = k.to_s
      field_value = v.get_value(i)
      assert_method(obj, "#{field_name}=", "#{model_name.camelcase} doesn't have #{field_name}= method!") do
        obj.send("#{field_name}=", field_value)
      end
    end
    
    assert_method(obj, "save", "#{model_name.camelcase} doesn't have save method.  Data will not be saved!") do
      obj.save
    end
    
    ret_arr << obj
  end
  Mack::Data::RegistryMap.reset!
  
  return ret_arr[0] if ret_arr.size == 1
  return ret_arr
end

#field(model_attrib_sym, options = {}, &block) ⇒ Object

Define a field for the factory class, and set the name of the field, any options for the field, and optionally specify a block that serves as the custom content generator.

The options can be categorized into the following:

  • default value (e.g. :default_value => “foo”)

  • whether it’s immutable or not (e.g. :immutable => true, and by default it’s false)

  • the field’s content type (e.g. :content => :alpha)

  • and the rules on how to generate the content (rules are contextually dependent on the content type).

Example:

class UserFactory
  include Mack::Data::Factory
  field :full_name, :content => :name
  field :created_at, :content => :time, :start_time => 2.days.ago, :end_time => 1.day.from_now
end

The following are all the supported content types and its rules:

Strings and Numbers

  • :alpha –> alphabets. rules: [:length, :min_length, :max_length]

  • :alphanumeric –> alphabets and number. rules: same as :alpha

  • :numeric –> numbers [optional, because if the field’s default value is number, its content type will automatically set to numeric)

Time and Money

  • :time –> generate random time object. rules: [:start_time, :end_time]. It will generate random time between the given start and end time if available, otherwise it’ll generate random time between ‘now’ and 1 day from ‘now’

  • :money –> generate random amount of money. rules: [:min, :max]. It will generate random money amount (of BigDecimal type) between the given min and max amount.

Internet related content

  • :email –> generate random email address

  • :username –> generate random username

  • :domain –> generate random domain name

Name related info

  • :firstname –> generate first name

  • :lastname –> generate last name

  • :name –> generate full name

Address related info

  • :city –> generate city name

  • :streetname –> generate street name

  • :state –> generate state. rules: [:country –> :us or :uk, :abbr –> true if you want a abbreviated state name (us only)]

  • :zipcode –> generate zipcode. rules: [:country –> :us or :uk]

  • :phone –> generate phone number

Company info

  • :company –> generate company name. rules: [:include_bs –> include sales tag line] example: field, :content => :company, :include_bs => true could generate something like:

    Fadel-Larkin
    monetize cross-media experiences
    

Parameters:

model_attrib_sym: the name of the field
options: the options for the field.  
block: the optional custom content generator


166
167
168
# File 'lib/mack-data_factory/data_factory.rb', line 166

def field(model_attrib_sym, options = {}, &block)
  field_manager.add(scope, model_attrib_sym, options, &block)
end

#scope_for(tag) ⇒ Object

Define a scope in the factory. Any field defined in a scope will overwrite its sibling in the default scope.

Parameters:

tag: name of the scope


205
206
207
208
209
# File 'lib/mack-data_factory/data_factory.rb', line 205

def scope_for(tag)
  set_scope(tag)
  yield
  set_scope(:default)
end