conject 0.0.1 → 0.0.3

Sign up to get free protection for your applications and to get access to all the features.
data/.gitignore CHANGED
@@ -1,4 +1,6 @@
1
1
  /coverage
2
2
  tags
3
3
  *.swp
4
+ *.swo
5
+ pkg
4
6
  /README.html
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- conject (0.0.1)
4
+ conject (0.0.2)
5
5
 
6
6
  GEM
7
7
  remote: https://rubygems.org/
@@ -1,5 +1,16 @@
1
1
  require "conject/version"
2
2
 
3
+ require 'conject/object_definition'
4
+ require 'conject/extended_metaid'
5
+ require 'conject/class_ext_construct_with'
6
+ require 'conject/object_context'
7
+ require 'conject/object_factory'
8
+ require 'conject/class_finder'
9
+ require 'conject/dependency_resolver'
10
+ require 'conject/utilities'
11
+ require 'conject/composition_error'
12
+ require 'conject/borrowed_active_support_inflector'
13
+
3
14
  module Conject
4
15
  #
5
16
  # Provide access to the default ObjectContext.
@@ -11,30 +22,17 @@ module Conject
11
22
  end
12
23
 
13
24
  def self.default_object_factory
14
- @default_object_factory ||= Conject::ObjectFactory.new(
15
- :class_finder => Conject::ClassFinder.new,
16
- :dependency_resolver => Conject::DependencyResolver.new
25
+ @default_object_factory ||= ObjectFactory.new(
26
+ :class_finder => ClassFinder.new,
27
+ :dependency_resolver => DependencyResolver.new
17
28
  )
18
29
  end
19
30
 
20
31
  def self.create_object_context(parent_context, object_factory=nil)
21
32
  object_factory ||= default_object_factory
22
- Conject::ObjectContext.new(
33
+ ObjectContext.new(
23
34
  :parent_context => parent_context,
24
35
  :object_factory => object_factory
25
36
  )
26
37
  end
27
38
  end
28
-
29
- # The rest of the libraries namespace themselves under Conject so
30
- # they must be required AFTER the initial definition of Conject.
31
- require 'conject/object_definition'
32
- require 'conject/extended_metaid'
33
- require 'conject/class_ext_construct_with'
34
- require 'conject/object_context'
35
- require 'conject/object_factory'
36
- require 'conject/class_finder'
37
- require 'conject/dependency_resolver'
38
- require 'conject/utilities'
39
- require 'conject/composition_error'
40
- require 'conject/borrowed_active_support_inflector'
@@ -1,11 +1,13 @@
1
1
 
2
- class Conject::ClassFinder
3
- def find_class(name)
4
- cname = name.to_s.camelize
5
- if Object.const_defined?(cname)
6
- Object.const_get(cname)
7
- else
8
- raise "Could not find class for #{name}"
2
+ module Conject
3
+ class ClassFinder
4
+ def find_class(name)
5
+ cname = name.to_s.camelize
6
+ if Object.const_defined?(cname)
7
+ Object.const_get(cname)
8
+ else
9
+ raise "Could not find class for #{name}"
10
+ end
9
11
  end
10
12
  end
11
13
  end
@@ -1,33 +1,35 @@
1
1
  require 'set'
2
2
 
3
- class Conject::CompositionError < ArgumentError
4
- def initialize(opts=nil)
5
- opts ||= {}
6
- object_def = opts[:object_definition]
7
- required = nil
8
- required = object_def.component_names if object_def
9
- provided = opts[:provided] || []
10
-
11
- msg = "Unexpected CompositionError"
12
-
13
- if object_def.nil?
14
- msg = "Failed to construct... something."
15
- if provided and !provided.empty?
16
- msg << " Provided objects were: #{provided.inspect}"
17
- end
3
+ module Conject
4
+ class CompositionError < ArgumentError
5
+ def initialize(opts=nil)
6
+ opts ||= {}
7
+ object_def = opts[:object_definition]
8
+ required = nil
9
+ required = object_def.component_names if object_def
10
+ provided = opts[:provided] || []
18
11
 
19
- elsif object_def and required and provided
20
- owner = object_def.owner || "object"
21
- msg = "Wrong components when building new #{owner}."
12
+ msg = "Unexpected CompositionError"
22
13
 
23
- missing = required - provided
24
- msg << " Missing required object(s) #{missing.to_a.inspect}." unless missing.empty?
14
+ if object_def.nil?
15
+ msg = "Failed to construct... something."
16
+ if provided and !provided.empty?
17
+ msg << " Provided objects were: #{provided.inspect}"
18
+ end
25
19
 
26
- unexpected = provided - required
27
- msg << " Unexpected object(s) provided #{unexpected.to_a.inspect}." unless unexpected.empty?
20
+ elsif object_def and required and provided
21
+ owner = object_def.owner || "object"
22
+ msg = "Wrong components when building new #{owner}."
28
23
 
29
- end
24
+ missing = required - provided
25
+ msg << " Missing required object(s) #{missing.to_a.inspect}." unless missing.empty?
26
+
27
+ unexpected = provided - required
28
+ msg << " Unexpected object(s) provided #{unexpected.to_a.inspect}." unless unexpected.empty?
30
29
 
31
- super msg
30
+ end
31
+
32
+ super msg
33
+ end
32
34
  end
33
35
  end
@@ -1,16 +1,18 @@
1
- class Conject::DependencyResolver
2
- #
3
- # Given a Class, generate a map of dependencies needed to construct a new
4
- # instance of that class. Dependencies are looked up (and/or instantiated, as
5
- # determined within the ObjectContext) via the provided ObjectContext.
6
- #
7
- # This method assumes the Class has_object_defintion? (Client code should
8
- # determine that before invoking this method.)
9
- #
10
- def resolve_for_class(klass, object_context)
11
- klass.object_definition.component_names.inject({}) do |obj_map, name|
12
- obj_map[name] = object_context.get(name)
13
- obj_map
1
+ module Conject
2
+ class DependencyResolver
3
+ #
4
+ # Given a Class, generate a map of dependencies needed to construct a new
5
+ # instance of that class. Dependencies are looked up (and/or instantiated, as
6
+ # determined within the ObjectContext) via the provided ObjectContext.
7
+ #
8
+ # This method assumes the Class has_object_defintion? (Client code should
9
+ # determine that before invoking this method.)
10
+ #
11
+ def resolve_for_class(klass, object_context)
12
+ klass.object_definition.component_names.inject({}) do |obj_map, name|
13
+ obj_map[name] = object_context.get(name)
14
+ obj_map
15
+ end
14
16
  end
15
17
  end
16
18
  end
@@ -1,61 +1,61 @@
1
- class Conject::ObjectContext
1
+ module Conject
2
+ class ObjectContext
2
3
 
3
- construct_with :parent_context, :object_factory
4
+ construct_with :parent_context, :object_factory
4
5
 
5
- def initialize
6
- @cache = {}
7
- end
8
-
9
- # Inject a named object into this context
10
- def put(name, object)
11
- @cache[name.to_sym] = object
12
- end
6
+ def initialize
7
+ @cache = { :this_object_context => self }
8
+ end
13
9
 
14
- alias_method :[]=, :put
10
+ # Inject a named object into this context
11
+ def put(name, object)
12
+ @cache[name.to_sym] = object
13
+ end
15
14
 
16
- # Retrieve a named object from this context.
17
- # If the object is already existant in this context, return it.
18
- # If we have a parent context and it contains the requested object, get and return object from parent context. (Recursive upward search)
19
- # If the object exists nowhere in this or a super context: construct, cache and return a new instance of the requested object using the object factory.
20
- def get(name)
21
- name = name.to_sym
22
- object = @cache[name]
23
- return @cache[name] if @cache.keys.include?(name)
24
-
25
- if parent_context and parent_context.has?(name)
26
- return parent_context.get(name)
27
- else
28
- object = object_factory.construct_new(name,self)
29
- @cache[name] = object
30
- return object
15
+ alias_method :[]=, :put
16
+
17
+ # Retrieve a named object from this context.
18
+ # If the object is already existant in this context, return it.
19
+ # If we have a parent context and it contains the requested object, get and return object from parent context. (Recursive upward search)
20
+ # If the object exists nowhere in this or a super context: construct, cache and return a new instance of the requested object using the object factory.
21
+ def get(name)
22
+ name = name.to_sym
23
+ object = @cache[name]
24
+ return @cache[name] if @cache.keys.include?(name)
25
+
26
+ if parent_context and parent_context.has?(name)
27
+ return parent_context.get(name)
28
+ else
29
+ object = object_factory.construct_new(name,self)
30
+ @cache[name] = object
31
+ return object
32
+ end
31
33
  end
32
- end
33
34
 
34
- alias_method :[], :get
35
+ alias_method :[], :get
35
36
 
36
- # Indicates if this context, or any parent context, contains the requested object in its cache.
37
- def has?(name)
38
- return true if directly_has?(name)
37
+ # Indicates if this context, or any parent context, contains the requested object in its cache.
38
+ def has?(name)
39
+ return true if directly_has?(name)
39
40
 
40
- # Ask parent (if i have a parent) if I don't have the object:
41
- if !parent_context.nil?
42
- return parent_context.has?(name)
43
- else
44
- # I don't have it, and neither do my ancestors.
45
- return false
41
+ # Ask parent (if i have a parent) if I don't have the object:
42
+ if !parent_context.nil?
43
+ return parent_context.has?(name)
44
+ else
45
+ # I don't have it, and neither do my ancestors.
46
+ return false
47
+ end
48
+ end
49
+
50
+ # Indicates if this context has the requested object in its own personal cache.
51
+ # (Does not consult any parent contexts.)
52
+ def directly_has?(name)
53
+ @cache.keys.include?(name.to_sym)
46
54
  end
47
- end
48
-
49
- # Indicates if this context has the requested object in its own personal cache.
50
- # (Does not consult any parent contexts.)
51
- def directly_has?(name)
52
- @cache.keys.include?(name.to_sym)
53
- end
54
55
 
55
- def in_subcontext
56
- yield Conject.create_object_context(self) if block_given?
57
- end
56
+ def in_subcontext
57
+ yield Conject.create_object_context(self) if block_given?
58
+ end
58
59
 
60
+ end
59
61
  end
60
-
61
-
@@ -1,10 +1,11 @@
1
+ module Conject
1
2
 
2
- class Conject::ObjectDefinition
3
- attr_reader :component_names, :owner
3
+ class ObjectDefinition
4
+ attr_reader :component_names, :owner
4
5
 
5
- def initialize(opts={})
6
- @owner = opts[:owner]
7
- @component_names = opts[:component_names] || []
6
+ def initialize(opts={})
7
+ @owner = opts[:owner]
8
+ @component_names = opts[:component_names] || []
9
+ end
8
10
  end
9
11
  end
10
-
@@ -1,28 +1,30 @@
1
1
 
2
- class Conject::ObjectFactory
3
- construct_with :class_finder, :dependency_resolver
2
+ module Conject
3
+ class ObjectFactory
4
+ construct_with :class_finder, :dependency_resolver
4
5
 
5
- def construct_new(name, object_context)
6
+ def construct_new(name, object_context)
6
7
 
7
- #
8
- # This implementation is what I'm loosely calling "type 1" or "regular" object creation:
9
- # - Assume we're looking for a class to create an instance with
10
- # - it may or may not have a declared list of named objects it needs to be constructed with
11
- #
8
+ #
9
+ # This implementation is what I'm loosely calling "type 1" or "regular" object creation:
10
+ # - Assume we're looking for a class to create an instance with
11
+ # - it may or may not have a declared list of named objects it needs to be constructed with
12
+ #
12
13
 
13
- klass = class_finder.find_class(name)
14
+ klass = class_finder.find_class(name)
14
15
 
15
- if klass.has_object_definition?
16
- object_map = dependency_resolver.resolve_for_class(klass, object_context)
17
- return klass.new(object_map)
16
+ if klass.has_object_definition?
17
+ object_map = dependency_resolver.resolve_for_class(klass, object_context)
18
+ return klass.new(object_map)
18
19
 
19
- elsif Conject::Utilities.has_zero_arg_constructor?(klass)
20
- # Default construction
21
- return klass.new
22
- else
23
- # Oops, out of ideas on how to build.
24
- raise ArgumentError.new("Class #{klass} has no special component needs, but neither does it have a zero-argument constructor.");
25
- end
20
+ elsif Utilities.has_zero_arg_constructor?(klass)
21
+ # Default construction
22
+ return klass.new
23
+ else
24
+ # Oops, out of ideas on how to build.
25
+ raise ArgumentError.new("Class #{klass} has no special component needs, but neither does it have a zero-argument constructor.");
26
+ end
26
27
 
28
+ end
27
29
  end
28
30
  end
@@ -1,8 +1,10 @@
1
- module Conject::Utilities
2
- class << self
3
- def has_zero_arg_constructor?(klass)
4
- init_arity = klass.instance_method(:initialize).arity
5
- init_arity == 0 or (RUBY_VERSION <= "1.9.2" and init_arity == -1)
1
+ module Conject
2
+ module Utilities
3
+ class << self
4
+ def has_zero_arg_constructor?(klass)
5
+ init_arity = klass.instance_method(:initialize).arity
6
+ init_arity == 0 or (RUBY_VERSION <= "1.9.2" and init_arity == -1)
7
+ end
6
8
  end
7
9
  end
8
10
  end
@@ -1,3 +1,3 @@
1
1
  module Conject
2
- VERSION = "0.0.1"
2
+ VERSION = "0.0.3"
3
3
  end
@@ -0,0 +1,28 @@
1
+ require File.expand_path(File.dirname(__FILE__) + "/../../spec_helper")
2
+
3
+ describe "object referencing its own context" do
4
+ subject { Conject.default_object_context }
5
+
6
+ before do
7
+ append_test_load_path "basic_composition"
8
+ require 'master_of_puppets'
9
+ end
10
+
11
+ after do
12
+ restore_load_path
13
+ end
14
+
15
+ it "ObjectContext caches a reference to itself using the name :this_object_context" do
16
+ subject[:this_object_context].should == subject
17
+ end
18
+
19
+ it "an object can inject :this_object_context as a reference to its constructing ObjectContext" do
20
+ master = subject.get('master_of_puppets')
21
+ master.this_object_context.should == subject
22
+
23
+ master.this_object_context.get('master_of_puppets').should == master
24
+ end
25
+
26
+
27
+ end
28
+
@@ -0,0 +1,5 @@
1
+ class MasterOfPuppets
2
+ construct_with :this_object_context
3
+
4
+ public :this_object_context
5
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: conject
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.1
4
+ version: 0.0.3
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,11 +9,11 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2012-02-21 00:00:00.000000000 Z
12
+ date: 2012-02-28 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: rake
16
- requirement: &2152595540 !ruby/object:Gem::Requirement
16
+ requirement: &2152364960 !ruby/object:Gem::Requirement
17
17
  none: false
18
18
  requirements:
19
19
  - - ! '>='
@@ -21,10 +21,10 @@ dependencies:
21
21
  version: '0'
22
22
  type: :development
23
23
  prerelease: false
24
- version_requirements: *2152595540
24
+ version_requirements: *2152364960
25
25
  - !ruby/object:Gem::Dependency
26
26
  name: rspec
27
- requirement: &2152595120 !ruby/object:Gem::Requirement
27
+ requirement: &2152364540 !ruby/object:Gem::Requirement
28
28
  none: false
29
29
  requirements:
30
30
  - - ! '>='
@@ -32,10 +32,10 @@ dependencies:
32
32
  version: '0'
33
33
  type: :development
34
34
  prerelease: false
35
- version_requirements: *2152595120
35
+ version_requirements: *2152364540
36
36
  - !ruby/object:Gem::Dependency
37
37
  name: simplecov
38
- requirement: &2152594640 !ruby/object:Gem::Requirement
38
+ requirement: &2152364060 !ruby/object:Gem::Requirement
39
39
  none: false
40
40
  requirements:
41
41
  - - ! '>='
@@ -43,7 +43,7 @@ dependencies:
43
43
  version: '0'
44
44
  type: :development
45
45
  prerelease: false
46
- version_requirements: *2152594640
46
+ version_requirements: *2152364060
47
47
  description: Enable Guice-like dependency injection and contextual object interactions.
48
48
  email:
49
49
  - david.crosby@atomicobject.com
@@ -77,6 +77,7 @@ files:
77
77
  - spec/acceptance/regression/README
78
78
  - spec/acceptance/regression/basic_composition_spec.rb
79
79
  - spec/acceptance/regression/basic_object_creation_spec.rb
80
+ - spec/acceptance/regression/inject_object_context_spec.rb
80
81
  - spec/acceptance/regression/nested_contexts_spec.rb
81
82
  - spec/conject/borrowed_active_support_inflector_spec.rb
82
83
  - spec/conject/class_ext_construct_with_spec.rb
@@ -96,6 +97,7 @@ files:
96
97
  - spec/test_data/basic_composition/grass.rb
97
98
  - spec/test_data/basic_composition/guest.rb
98
99
  - spec/test_data/basic_composition/lobby.rb
100
+ - spec/test_data/basic_composition/master_of_puppets.rb
99
101
  - spec/test_data/basic_composition/nails.rb
100
102
  - spec/test_data/basic_composition/tv.rb
101
103
  - spec/test_data/basic_composition/wood.rb
@@ -140,6 +142,7 @@ test_files:
140
142
  - spec/acceptance/regression/README
141
143
  - spec/acceptance/regression/basic_composition_spec.rb
142
144
  - spec/acceptance/regression/basic_object_creation_spec.rb
145
+ - spec/acceptance/regression/inject_object_context_spec.rb
143
146
  - spec/acceptance/regression/nested_contexts_spec.rb
144
147
  - spec/conject/borrowed_active_support_inflector_spec.rb
145
148
  - spec/conject/class_ext_construct_with_spec.rb
@@ -159,6 +162,7 @@ test_files:
159
162
  - spec/test_data/basic_composition/grass.rb
160
163
  - spec/test_data/basic_composition/guest.rb
161
164
  - spec/test_data/basic_composition/lobby.rb
165
+ - spec/test_data/basic_composition/master_of_puppets.rb
162
166
  - spec/test_data/basic_composition/nails.rb
163
167
  - spec/test_data/basic_composition/tv.rb
164
168
  - spec/test_data/basic_composition/wood.rb