Skip to content

Instantly share code, notes, and snippets.

@cupakromer
Last active December 25, 2015 17:39
Show Gist options
  • Save cupakromer/7015104 to your computer and use it in GitHub Desktop.
Save cupakromer/7015104 to your computer and use it in GitHub Desktop.
MetaProgram some factories
module ModelFactory
def self.factory(resource, defaults = {})
resource = resource.downcase
defaults = defaults.dup.freeze
resource_defaults = "default_#{resource}_attributes".to_sym
build_resource = "build_#{resource}".to_sym
create_resource = "create_#{resource}".to_sym
define_method resource_defaults do
defaults
end
module_function resource_defaults
define_method build_resource do |opts = {}|
opts = send(resource_defaults).merge(opts).reject{ |o| :optional == o }
opts.each{ |k, v| opts[k] = v.call if v.is_a? Proc }
klass = self.class.const_get(resource.to_s.classify)
klass.new(opts)
end
module_function build_resource
define_method create_resource do |opts = {}|
send(build_resource, opts).tap{ |r| r.save! }
end
module_function create_resource
end
factory :ewok
factory :wampa, { size: :small, fur: :brown }
factory :jedi, lightsaber: :green, delusion_of_grandeur: :optional
factory :rebel, { alliance: true, joined_at: ->{ 1.week.ago } }
end
module ModelFactory
FactoryNotFound = Class.new(RuntimeError)
def self.factories
@factories ||= {}
end
def self.factory(resource, defaults = {})
factories[resource] = defaults.dup.freeze
end
module_function
def factory_defaults(resource)
factories.fetch(resource) { raise FactoryNotFound, resource }
end
def build(resource, opts = {})
opts = factory_defaults(resource).merge(opts).reject{ |o| :optional == o }
opts.each{ |k, v| opts[k] = v.call if v.is_a? Proc }
resource.new(opts)
end
def create(resource, opts = {})
build(resource, opts).tap{ |r| r.save! }
end
end
module ModelFactory
factory Ewok
factory Wampa, { size: :small, fur: :brown }
factory Jedi, lightsaber: :green, delusion_of_grandeur: :optional
factory Rebel, { alliance: true, joined_at: ->{ 1.week.ago } }
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment