conject 0.0.1 → 0.0.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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