Skip to content

Instantly share code, notes, and snippets.

@mathie
Created April 7, 2010 04:36
Show Gist options
  • Save mathie/358529 to your computer and use it in GitHub Desktop.
Save mathie/358529 to your computer and use it in GitHub Desktop.

This was a quick hack attempt to create a simple factory_girl-like thing for objects that weren't ActiveRecord-based at all, just plain ol' objects with attr_accessors.

Didn't work quickly enough to pursue, but I didn't want to throw it away either. :-)

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
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment