|
def Factory(name, overrides = {}) |
|
Factory.build(name, overrides) |
|
end |
|
|
|
class Factory |
|
class << self |
|
attr_accessor :factories |
|
end |
|
self.factories = {} |
|
|
|
def self.define(name) |
|
instance = Factory.new(name) |
|
yield(instance) |
|
factories[instance.factory_name] = instance |
|
end |
|
|
|
def self.build(name, overrides) |
|
factories[name.to_sym].run(overrides) |
|
end |
|
|
|
attr_accessor :factory_name, :attributes |
|
|
|
def initialize(name) |
|
self.factory_name = name.to_sym |
|
self.attributes = {} |
|
end |
|
|
|
def add_attribute(name, value = nil, &block) |
|
if block_given? |
|
if value |
|
raise "Both value and block given" |
|
else |
|
attributes[name.to_sym] = block |
|
end |
|
else |
|
attributes[name.to_sym] = value |
|
end |
|
end |
|
|
|
def method_missing(name, *args, &block) |
|
add_attribute(name, *args, &block) |
|
end |
|
|
|
def run(overrides = {}) |
|
obj = class_for(factory_name).new |
|
attributes.each do |k, v| |
|
obj.send("#{k}=", v) |
|
end |
|
overrides.each do |k, v| |
|
obj.send("#{k}=", v) |
|
end |
|
obj |
|
end |
|
|
|
private |
|
def class_for(class_or_str) |
|
if class_or_str.respond_to?(:to_sym) |
|
Object.const_get(variable_name_to_class_name(class_or_str)) |
|
else |
|
class_or_str |
|
end |
|
end |
|
|
|
# Based on ActiveSupport's camelize inflector |
|
def variable_name_to_class_name(name) |
|
name.to_s. |
|
gsub(/\/(.?)/) { "::#{$1.upcase}" }. |
|
gsub(/(?:^|_)(.)/) { $1.upcase } |
|
end |
|
end |
|
|
|
Factory.define(:address) do |address| |
|
address.first_names 'Homer' |
|
address.surname 'Simpson' |
|
address.address_1 '744 Evergreen Terrace' |
|
address.city 'Springfield' |
|
address.post_code 'W1A 1AA' |
|
end |