Created
September 4, 2012 15:35
-
-
Save barinek/3622495 to your computer and use it in GitHub Desktop.
Guice-ish
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
require "singleton" | |
require "i18n" | |
require "active_support" | |
require "active_support/core_ext/string" | |
module Guice | |
def inject(*klass_symbols) | |
@injections = Hash.new unless @injections | |
@injections[self.name] = klass_symbols | |
end | |
def injections | |
@injections ||= Hash.new | |
@injections[self.name] || [] | |
end | |
class Injector | |
include Singleton | |
def self.configure_injector(&block) | |
raise "Sorry, requires a block." unless block | |
raise "Sorry, already configured." if instance.configured | |
block.call(instance) | |
instance.instance_variable_set(:@configured, true) | |
instance | |
end | |
def initialize | |
@known_bindings = Hash.new | |
@known_instances = Hash.new | |
@configured = false | |
end | |
def configured | |
@configured | |
end | |
def bind(klass) | |
@known_bindings[klass.name] = klass | |
end | |
def get_instance(klass) | |
raise "Sorry, not configured." unless @configured | |
get_deep_instance(klass) | |
end | |
def get_deep_instance(klass, parents = []) | |
instance = @known_instances[klass.name] | |
return instance if instance | |
if klass.kind_of?(Guice) | |
parameters = klass.instance_method(:initialize).parameters.collect { |param| param[1] } | |
if (parameters.eql?(klass.injections)) | |
parameter_instances = parameters.collect do |parameter| | |
return nil if parents.include?(parameter.to_s.camelize.constantize) | |
get_deep_instance(parameter.to_s.camelize.constantize, parents.push(klass)) | |
end | |
raise "Sorry, possible circular dependency found." if parameter_instances.any? { |parameter_instance| parameter_instance.nil? } | |
@known_instances[klass.name] = klass.new(*parameter_instances) | |
end | |
else | |
begin | |
@known_instances[klass.name] = klass.new | |
rescue | |
raise "Sorry, unknown constructor args." | |
end | |
end | |
@known_instances[klass.name] | |
end | |
end | |
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
require "rspec" | |
describe Module do | |
before(:all) do | |
@injector = Guice::Injector.configure_injector do |injector| | |
injector.bind(Foo) | |
injector.bind(Bar) | |
injector.bind(Cart) | |
injector.bind(Horse) | |
injector.bind(Fiz) | |
injector.bind(Buz) | |
end | |
end | |
it "can't be created" do | |
lambda do | |
Guice::Injector.new | |
end.should raise_error | |
end | |
it "requires a block" do | |
lambda do | |
Guice::Injector.configure_injector | |
end.should raise_error("Sorry, requires a block.") | |
end | |
it "complains about being configured twice" do | |
lambda do | |
Guice::Injector.configure_injector do |injector| | |
injector.bind(Foo) | |
end | |
end.should raise_error("Sorry, already configured.") | |
end | |
it "injects bar" do | |
foo = @injector.get_instance(Foo) | |
foo.bar.should be | |
end | |
it "complains about circular dependencies" do | |
lambda { @injector.get_instance(Cart) }.should raise_error("Sorry, possible circular dependency found.") | |
lambda { @injector.get_instance(Horse) }.should raise_error("Sorry, possible circular dependency found.") | |
end | |
it "complains about unknown constructor args" do | |
lambda { @injector.get_instance(Fiz) }.should raise_error("Sorry, unknown constructor args.") | |
end | |
class Foo | |
extend Guice | |
inject :bar | |
def initialize(bar) | |
@bar = bar | |
end | |
def bar | |
@bar | |
end | |
end | |
class Bar | |
end | |
class Cart | |
extend Guice | |
inject :horse | |
def initialize(horse) | |
end | |
end | |
class Horse | |
extend Guice | |
inject :cart | |
def initialize(cart) | |
end | |
end | |
class Fiz | |
extend Guice | |
inject :buz | |
def initialize(buz) | |
end | |
end | |
class Buz | |
def initialize(bop) | |
end | |
end | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment