Skip to content

Instantly share code, notes, and snippets.

@ignacy
Created February 4, 2016 07:17
Show Gist options
  • Save ignacy/0ad208d0cf4906d3aac4 to your computer and use it in GitHub Desktop.
Save ignacy/0ad208d0cf4906d3aac4 to your computer and use it in GitHub Desktop.
rozwiazanko
require 'factory_boy/factory'
require 'factory_boy/errors'
require 'factory_boy/factory_identifier'
require 'factory_boy/factory_register'
module FactoryBoy
@defined_factories = FactoryRegister.new
def self.clear_factories
@defined_factories = FactoryRegister.new
end
def self.defined_factories
@defined_factories
end
def self.define_factory(klass, options = {}, &block)
factory = Factory.new(&block)
factory.instance_eval(&block) if block_given?
@defined_factories[FactoryIdentifier.new(klass, options)] = factory
end
def self.build(klass, attributes = {})
factory_key, builder = @defined_factories.find(FactoryIdentifier.new(klass))
factory_key.object_klass.new.tap do |instance|
builder.attributes.merge(attributes).each do |name, value|
fail Errors::NotExistingAttribute.new(name) unless instance.respond_to?("#{name}=")
instance.public_send("#{name}=", value)
end
end
end
end
class Factory < BasicObject
def initialize(&block)
@attributes = {}
end
def method_missing(attribute_name, *parameters, &block)
attributes[attribute_name] = parameters.first
end
attr_reader :attributes
end
class FactoryIdentifier
def initialize(class_or_symbol, opts = {})
if class_or_symbol.is_a? Symbol
@symbol = class_or_symbol
@object_klass = class_if_possible(opts[:class], class_or_symbol.capitalize)
else
@symbol = class_or_symbol.name.downcase.to_sym
@object_klass = class_or_symbol
end
end
attr_reader :symbol, :object_klass
def ==(other)
self.class === other and other.symbol == @symbol
end
def hash
@symbol.hash
end
alias eql? ==
private
def class_if_possible(options_class, symbol)
options_class || (Object.const_defined?(symbol) && Object.const_get(symbol))
end
end
module FactoryBoy
class FactoryRegister
include Enumerable
attr_accessor :factories
def initialize(factories = {})
@factories = factories
end
def each
@factories.map { |f| yield f }
end
def []=(identifier, factory)
@factories[identifier] = factory
end
def find(identifier)
matching_factory = @factories.select { |x| x.symbol == identifier.symbol }
fail Errors::UndefinedFactory.new unless matching_factory.any?
matching_factory.first.to_a
end
end
end
module FactoryBoy
module Errors
UndefinedFactory = Class.new(StandardError)
NotExistingAttribute = Class.new(StandardError)
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment