Skip to content

Instantly share code, notes, and snippets.

@ignar
Created May 6, 2016 12:15
Show Gist options
  • Save ignar/d5c713e8cc007cab5364553cd7fcd97a to your computer and use it in GitHub Desktop.
Save ignar/d5c713e8cc007cab5364553cd7fcd97a to your computer and use it in GitHub Desktop.
require 'active_support/all'
class User
attr_accessor :name, :admin
def initialize(options = {}, &block)
options.each do |k,v|
self.public_send "#{k}=", v
end
end
end
class UserJob
attr_accessor :name, :admin
def initialize(name, options = {})
self.name = name
options.each do |k,v|
self.public_send "#{k}=", v
end
end
end
module Klassifier
def get_klass(klass)
_klass = klass
if klass.is_a?(Symbol) || klass.is_a?(String)
_klass = klass.to_s.classify.constantize
end
_klass
end
end
class FactoryBoy
extend Klassifier
class InvalidArg < StandardError; end
class NotRegistered < StandardError; end
class Registry
include Singleton
include Klassifier
attr_accessor :factories
def push(klass, args, &block)
self.factories ||= {}
factories[get_klass(klass)] = {args: args, block: block}
end
def get(klass)
factories[get_klass(klass)]
end
def clear
self.factories = {}
end
end
class << self
def register(klass, *args, &block)
Registry.instance.push(klass, args, &block)
end
def clear
Registry.instance.clear
end
def create(klass, *arg, &block)
_klass = get_klass(klass)
raise NotRegistered unless Registry.instance.get(_klass)
raise InvalidArg unless _klass.respond_to?(:new)
inst = _klass.new(*arg)
if block_given?
Class.new do
def initialize(inst); @inst = inst; end
def method_missing(method, *args)
@inst.public_send("#{method}=", *args)
end
end.new(inst).instance_eval(&block)
end
inst
end
end
end
describe FactoryBoy::Registry do
before { described_class.instance.clear }
context 'with no args' do
it 'should register' do
FactoryBoy.register(:user)
expect(described_class.instance.get(:user)).to be_kind_of(Hash)
end
end
context 'with args' do
it 'should register' do
attrs = {name: 'name'}
FactoryBoy.register(:user, attrs)
factory = described_class.instance.get(:user)
expect(factory).to be_kind_of(Hash)
expect(factory[:args]).to eq([attrs])
end
it 'when params' do
attrs = {name: 'name'}
name = 'name'
FactoryBoy.register(:user_job, name, attrs)
factory = described_class.instance.get(:user_job)
expect(factory).to be_kind_of(Hash)
expect(factory[:args]).to eq([name, attrs])
end
it 'when params' do
FactoryBoy.register(:user){ admin true }
factory = described_class.instance.get(:user)
expect(factory).to be_kind_of(Hash)
expect(factory[:block]).to be_kind_of(Proc)
end
end
end
describe FactoryBoy do
before { described_class.clear }
describe '.create' do
context 'not fail' do
it 'should return instance' do
described_class.register(User)
expect(described_class.create(User)).to be_an_instance_of(User)
end
it 'should return instance' do
described_class.register(:user)
expect(described_class.create(:user)).to be_an_instance_of(User)
end
it 'should return instance' do
described_class.register(:user_job)
expect(described_class.create(:user_job, 'me')).to be_an_instance_of(UserJob)
end
context 'with args' do
before do
described_class.register(:user_job)
end
it 'should return instance' do
expect(described_class.create(:user_job, 'name')).to be_an_instance_of(UserJob)
end
it 'should correctly assign attrs' do
name = 'name'
inst = described_class.create(:user_job, name)
expect(inst.name).to eq(name)
end
it 'should correctly assign attrs' do
name = 'name'
admin = true
inst = described_class.create(:user_job, name, admin: admin)
expect(inst.name).to eq(name)
expect(inst.admin).to eq(admin)
end
it 'should correctly assign attrs' do
name = 'name'
admin = true
inst = described_class.create(:user_job, name){ admin true }
expect(inst.name).to eq(name)
expect(inst.admin).to eq(admin)
end
end
context 'with register' do
end
end
context 'fail' do
it 'should fail unless arg is klass' do
module Foo; end
described_class.register(Foo)
expect {
described_class.create(Foo)
}.to raise_error(described_class::InvalidArg)
end
end
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment