codeine 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,5 @@
1
+ *.gem
2
+ .bundle
3
+ Gemfile.lock
4
+ pkg/*
5
+ *.swp
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source "http://rubygems.org"
2
+
3
+ # Specify your gem's dependencies in codeine.gemspec
4
+ gemspec
data/LICENSE ADDED
@@ -0,0 +1,8 @@
1
+ Copyright (c) 2011 Tim Ariyeh
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
4
+
5
+ The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
6
+
7
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
8
+
@@ -0,0 +1 @@
1
+ require "bundler/gem_tasks"
@@ -0,0 +1,22 @@
1
+ # -*- encoding: utf-8 -*-
2
+ $:.push File.expand_path("../lib", __FILE__)
3
+ require "codeine/version"
4
+
5
+ Gem::Specification.new do |s|
6
+ s.name = "codeine"
7
+ s.version = Codeine::VERSION
8
+ s.authors = ["Tim Ariyeh"]
9
+ s.email = ["tim.ariyeh@gmail.com"]
10
+ s.homepage = "https://github.com/timariyeh/codeine"
11
+ s.summary = %q{A simple Ruby dependency injector}
12
+ s.description = %q{A really simple, partitionable, ruby-flavored dependency injector}
13
+
14
+ s.rubyforge_project = "codeine"
15
+
16
+ s.files = `git ls-files`.split("\n")
17
+ s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
18
+ s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
19
+ s.require_paths = ["lib"]
20
+
21
+ s.add_development_dependency "rspec"
22
+ end
@@ -0,0 +1,32 @@
1
+ $LOAD_PATH.unshift File.dirname(__FILE__) + '/../lib'
2
+ require 'codeine'
3
+
4
+
5
+ module FooModule
6
+ class A
7
+ codeine_inject :logger
8
+ def initialize
9
+ puts logger.inspect
10
+ end
11
+ end
12
+ end
13
+
14
+ module BarModule
15
+ class A
16
+ codeine_inject :logger
17
+ def initialize
18
+ puts logger.inspect
19
+ end
20
+ end
21
+ end
22
+
23
+
24
+ container_foo = Codeine.container_for(FooModule)
25
+ container_foo.register(:logger){"the fancy logger for FooModule"}
26
+
27
+ container_bar = Codeine.container_for(BarModule)
28
+ container_bar.register(:logger){"the simple logger for BarModule"}
29
+
30
+
31
+ FooModule::A.new
32
+ BarModule::A.new
@@ -0,0 +1,26 @@
1
+ $LOAD_PATH.unshift File.dirname(__FILE__) + '/../lib'
2
+ require 'codeine'
3
+
4
+ Codeine.activate
5
+ Codeine.register(:logger){"some logger"}
6
+
7
+ module FooModule
8
+ class A
9
+ codeine_inject :logger
10
+ def initialize
11
+ puts logger.inspect
12
+ end
13
+ end
14
+ end
15
+
16
+ module BarModule
17
+ class A
18
+ codeine_inject :logger
19
+ def initialize
20
+ puts logger.inspect
21
+ end
22
+ end
23
+ end
24
+
25
+ FooModule::A.new
26
+ BarModule::A.new
@@ -0,0 +1,59 @@
1
+ require "codeine/version"
2
+ require "codeine/container"
3
+ require "codeine/injectable"
4
+ require "codeine/containable"
5
+
6
+ module Codeine
7
+ class << self
8
+
9
+ #automatically called later in this file
10
+ def activate()
11
+ Module.send(:include, Codeine::Containable)
12
+ Class.send(:include, Codeine::Injectable)
13
+ end
14
+
15
+ def container_for(mod)
16
+ mod.codeine_container ||= Container.new
17
+ end
18
+
19
+ def default_container
20
+ @default_container ||= Container.new
21
+ end
22
+
23
+ def register(service, &block)
24
+ default_container.register(service, &block)
25
+ end
26
+
27
+ def get(service)
28
+ default_container.get(service)
29
+ end
30
+ alias :[] :get
31
+
32
+ end
33
+
34
+ module Utility
35
+ class << self
36
+ def constant_path(constant)
37
+ constants = []
38
+ parts = constant.to_s.split("::")
39
+ parts.count.times do |i|
40
+ constants << parts[0..i].inject(Kernel) do |memo, obj|
41
+ memo.const_get(obj)
42
+ end
43
+ end
44
+ constants
45
+ end
46
+
47
+ def nearest_container(constant)
48
+ container = nil
49
+ constant_path(constant).reverse.each do |c|
50
+ next unless c.respond_to? :codeine_container
51
+ break if container = c.codeine_container
52
+ end
53
+ container || ::Codeine.default_container
54
+ end
55
+ end
56
+ end
57
+ end
58
+
59
+ Codeine.activate
@@ -0,0 +1,8 @@
1
+
2
+ module Codeine
3
+ module Containable
4
+
5
+ attr_accessor :codeine_container
6
+
7
+ end
8
+ end
@@ -0,0 +1,33 @@
1
+
2
+ module Codeine
3
+ class Container
4
+
5
+ def services
6
+ @services ||= {}
7
+ end
8
+
9
+ def filters
10
+ @filters ||= []
11
+ end
12
+
13
+ def register(key, &block)
14
+ services[key.to_sym] = block
15
+ end
16
+
17
+ def get(key)
18
+ key = key.to_sym
19
+ service = services[key].call
20
+ filters.each do |f|
21
+ if key.to_s =~ f[:pattern]
22
+ f[:block].call(key, service)
23
+ end
24
+ end
25
+ service
26
+ end
27
+ alias :[] :get
28
+
29
+ def filter(pattern, &block)
30
+ filters.push :pattern => pattern, :block => block
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,22 @@
1
+
2
+ module Codeine
3
+ module Injectable
4
+
5
+ def nearest_codeine_container
6
+ Codeine::Utility.nearest_container(self)
7
+ end
8
+
9
+ def codeine_inject(service, method_name = nil)
10
+ method_name = method_name || service
11
+ define_method(method_name.to_sym) do
12
+ cache = instance_variable_get("@codeine_#{service}")
13
+ unless cache
14
+ cache = self.class.nearest_codeine_container[service.to_sym]
15
+ instance_variable_set("@codeine_#{service}", cache)
16
+ end
17
+ cache
18
+ end
19
+ end
20
+
21
+ end
22
+ end
@@ -0,0 +1,3 @@
1
+ module Codeine
2
+ VERSION = "0.0.1"
3
+ end
@@ -0,0 +1,46 @@
1
+ Codeine
2
+ =======
3
+
4
+ A simple dependency injector for ruby projects.
5
+
6
+ Despite how flexible ruby is, and despite the insistence of a large part of the community, I frequently run into the need on larger projects to centrally manage my dependencies. I end up building something like Codeine for each one, so I decided to build it one more time and re-use it.
7
+
8
+ Usage
9
+ -----
10
+
11
+ Codeine can operate as either a global or module-local dependency container. Using it globally is the least flexible, but presents the simplest syntax.
12
+
13
+ require 'codeine'
14
+ Codeine.register(:logger){Logger.new}
15
+
16
+ class Foo
17
+ codeine_inject :logger
18
+
19
+ def initialize
20
+ logger.log "Initialized..."
21
+ end
22
+ end
23
+
24
+
25
+ For library code, and for larger projects, it's probably a better idea to segregate the containers.
26
+
27
+ require 'codeine'
28
+
29
+
30
+ module ProjectA
31
+ class Foo
32
+ codeine_inject :logger
33
+
34
+ def initialize
35
+ logger.log "Initialized..."
36
+ end
37
+ end
38
+ end
39
+
40
+ container = Codeine.container_for(ProjectA)
41
+ container.register(:logger){Logger.new}
42
+
43
+ foo = ProjectA::Foo.new
44
+
45
+
46
+ The the container bound to the ProjectA module will only service injection requests from classes/modules that reside within it
@@ -0,0 +1,2 @@
1
+ --color
2
+
@@ -0,0 +1,31 @@
1
+ require_relative "spec_helper"
2
+ require 'codeine'
3
+
4
+
5
+ describe Codeine::Containable do
6
+ before(:each) do
7
+ module Foo
8
+ class Bar
9
+ end
10
+ end
11
+ end
12
+
13
+ it "should create getter/setter" do
14
+ Foo.send(:extend, Codeine::Containable)
15
+ Foo.should respond_to :codeine_container
16
+ Foo.should respond_to :codeine_container=
17
+ end
18
+
19
+ it "should store container at the instance level" do
20
+ Foo.send(:extend, Codeine::Containable)
21
+ Foo::Bar.send(:extend, Codeine::Containable)
22
+
23
+ Foo.codeine_container = "foo_container"
24
+ Foo::Bar.codeine_container = "bar_container"
25
+
26
+ Foo.codeine_container.should == "foo_container"
27
+ Foo::Bar.codeine_container.should == "bar_container"
28
+ end
29
+
30
+
31
+ end
@@ -0,0 +1,55 @@
1
+
2
+ require_relative "spec_helper"
3
+ require 'codeine'
4
+
5
+ describe Codeine::Container do
6
+ let(:container){Codeine::Container.new}
7
+
8
+ describe "#register" do
9
+ it "should accept a block and register it as a service" do
10
+ hash = Hash.new
11
+ container.register(:foo){hash}
12
+
13
+ container.services[:foo].call.should == hash
14
+ end
15
+ end
16
+
17
+ describe "#get" do
18
+ it "should execute the block registered at the given key" do
19
+ hash = Hash.new
20
+ container.register(:foo){hash}
21
+
22
+ container.get(:foo).should == hash
23
+ end
24
+
25
+ it "should be aliased to []" do
26
+ hash = Hash.new
27
+ container.register(:foo){hash}
28
+
29
+ container[:foo].should == hash
30
+ end
31
+ end
32
+
33
+ describe "#filter" do
34
+ it "should fire the given block when a key matches the given filter" do
35
+ hash = Hash.new
36
+ container.register(:foo){hash}
37
+ container.filter(/^foo/){|key, service|
38
+ service[:bar] = "baz"
39
+ }
40
+ service = container.get(:foo)
41
+ service[:bar].should == "baz"
42
+ end
43
+
44
+ it "shouldn't fire the given block when a key doesn't match the given filter" do
45
+ hash = Hash.new
46
+ container.register(:foo){hash}
47
+ container.filter(/^bar/){|key, service|
48
+ service[:bar] = "baz"
49
+ }
50
+ service = container.get(:foo)
51
+ service[:bar].should_not == "baz"
52
+ end
53
+ end
54
+
55
+ end
@@ -0,0 +1,31 @@
1
+
2
+ require_relative "spec_helper"
3
+ require 'codeine'
4
+
5
+
6
+ describe Codeine::Injectable do
7
+ before(:each) do
8
+ module Foo
9
+ class Bar
10
+ end
11
+ end
12
+ end
13
+
14
+ describe "dynamic methods" do
15
+ it "should create a module-level inject_service method" do
16
+ Foo::Bar.should_not respond_to(:inject_service)
17
+ Foo::Bar.send(:extend, Codeine::Injectable)
18
+ Foo::Bar.should respond_to(:codeine_inject)
19
+ end
20
+
21
+ it "should create a service getter for injected services" do
22
+ Foo::Bar.send(:extend, Codeine::Injectable)
23
+ Foo::Bar.send(:extend, Codeine::Containable)
24
+ Foo::Bar.codeine_container = {:bat => "man"}
25
+ Foo::Bar.codeine_inject(:bat)
26
+ bar = Foo::Bar.new
27
+ bar.bat.should == "man"
28
+ end
29
+ end
30
+
31
+ end
@@ -0,0 +1,7 @@
1
+ $LOAD_PATH.unshift "../lib"
2
+
3
+ RSpec.configure do |config|
4
+ config.after(:each) do
5
+ Object.send(:remove_const, :Foo) if Object.const_defined?(:Foo)
6
+ end
7
+ end
@@ -0,0 +1,48 @@
1
+ require_relative "spec_helper"
2
+ require 'codeine'
3
+
4
+
5
+ describe Codeine::Utility do
6
+ before(:each) do
7
+ module Foo
8
+ module Bar
9
+ class Baz
10
+
11
+ end
12
+ end
13
+ end
14
+ end
15
+
16
+ describe "constant_path" do
17
+ it "should return an array of constant values" do
18
+ path = Codeine::Utility.constant_path("Foo")
19
+ path[0].should == Foo
20
+ end
21
+
22
+ it "should return constant path in heirarchial order" do
23
+ path = Codeine::Utility.constant_path(Foo::Bar::Baz)
24
+ path.should == [Foo, Foo::Bar, Foo::Bar::Baz]
25
+ end
26
+ end
27
+
28
+ describe "nearest_container" do
29
+
30
+ it "should look up the constant heirarchy for a container" do
31
+ Foo.send(:extend, Codeine::Injectable)
32
+ Foo.send(:extend, Codeine::Containable)
33
+ Foo::Bar.send(:extend, Codeine::Injectable)
34
+ Foo.codeine_container = "foo_container"
35
+ Foo::Bar.nearest_codeine_container.should == "foo_container"
36
+ end
37
+
38
+ it "should not look down the constant heirarchy for a container" do
39
+ Foo.send(:extend, Codeine::Injectable)
40
+ Foo.send(:extend, Codeine::Containable)
41
+ Foo::Bar.send(:extend, Codeine::Injectable)
42
+ Foo::Bar.send(:extend, Codeine::Containable)
43
+
44
+ Foo::Bar.codeine_container = "bar_container"
45
+ Foo.nearest_codeine_container.should_not == "bar_container"
46
+ end
47
+ end
48
+ end
metadata ADDED
@@ -0,0 +1,75 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: codeine
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Tim Ariyeh
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2011-10-08 00:00:00.000000000Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: rspec
16
+ requirement: &13428680 !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ! '>='
20
+ - !ruby/object:Gem::Version
21
+ version: '0'
22
+ type: :development
23
+ prerelease: false
24
+ version_requirements: *13428680
25
+ description: A really simple, partitionable, ruby-flavored dependency injector
26
+ email:
27
+ - tim.ariyeh@gmail.com
28
+ executables: []
29
+ extensions: []
30
+ extra_rdoc_files: []
31
+ files:
32
+ - .gitignore
33
+ - Gemfile
34
+ - LICENSE
35
+ - Rakefile
36
+ - codeine.gemspec
37
+ - examples/flexible.rb
38
+ - examples/simple.rb
39
+ - lib/codeine.rb
40
+ - lib/codeine/containable.rb
41
+ - lib/codeine/container.rb
42
+ - lib/codeine/injectable.rb
43
+ - lib/codeine/version.rb
44
+ - readme.markdown
45
+ - spec/.rspec
46
+ - spec/containable_spec.rb
47
+ - spec/container_spec.rb
48
+ - spec/injectable_spec.rb
49
+ - spec/spec_helper.rb
50
+ - spec/utility_spec.rb
51
+ homepage: https://github.com/timariyeh/codeine
52
+ licenses: []
53
+ post_install_message:
54
+ rdoc_options: []
55
+ require_paths:
56
+ - lib
57
+ required_ruby_version: !ruby/object:Gem::Requirement
58
+ none: false
59
+ requirements:
60
+ - - ! '>='
61
+ - !ruby/object:Gem::Version
62
+ version: '0'
63
+ required_rubygems_version: !ruby/object:Gem::Requirement
64
+ none: false
65
+ requirements:
66
+ - - ! '>='
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ requirements: []
70
+ rubyforge_project: codeine
71
+ rubygems_version: 1.8.6
72
+ signing_key:
73
+ specification_version: 3
74
+ summary: A simple Ruby dependency injector
75
+ test_files: []