callme 0.5.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 22eae5e35215e5eed4a7876f1bdac5b8f8f9bcdb
4
+ data.tar.gz: 734e00afe63b56af60134a224acc0489ae09d481
5
+ SHA512:
6
+ metadata.gz: ab1b440d21c6f30ee6ff3d95b89d5462485bf5505a468994ee1712117dc3e5c2e6b019b6e17660313f6ecbb7937f1c539e286a98a3464e0cb5d8f091f6def3cd
7
+ data.tar.gz: be2243ddbedb38520e29e85e652db9f2a09a168d99ae89dec6c30e2e8e57925f2e95be4e35094eb342d87f0adc93137bfdcdd008d6782c7fae096667c852d55b
data/.gitignore ADDED
@@ -0,0 +1,5 @@
1
+ vendor/
2
+ tags
3
+ .bundle
4
+ .DS_Store
5
+ pkg
data/.travis.yml ADDED
@@ -0,0 +1,3 @@
1
+ rvm:
2
+ - 2.0.0
3
+ script: "bundle exec rspec spec/"
data/.yardops ADDED
@@ -0,0 +1 @@
1
+ lib/**/*.rb
data/Gemfile ADDED
@@ -0,0 +1,8 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in aggregate_builder.gemspec
4
+ gemspec
5
+
6
+ group :test do
7
+ gem 'rspec'
8
+ end
data/Gemfile.lock ADDED
@@ -0,0 +1,32 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ callme (0.5.0)
5
+ request_store
6
+
7
+ GEM
8
+ remote: https://rubygems.org/
9
+ specs:
10
+ diff-lcs (1.2.5)
11
+ rake (10.1.1)
12
+ request_store (1.0.5)
13
+ rspec (2.14.1)
14
+ rspec-core (~> 2.14.0)
15
+ rspec-expectations (~> 2.14.0)
16
+ rspec-mocks (~> 2.14.0)
17
+ rspec-core (2.14.7)
18
+ rspec-expectations (2.14.4)
19
+ diff-lcs (>= 1.1.3, < 2.0)
20
+ rspec-mocks (2.14.4)
21
+
22
+ PLATFORMS
23
+ ruby
24
+
25
+ DEPENDENCIES
26
+ bundler (~> 1.3)
27
+ callme!
28
+ rake
29
+ rspec
30
+
31
+ BUNDLED WITH
32
+ 1.14.6
data/LICENSE.txt ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2013 Albert Gazizov
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,147 @@
1
+ # Callme [![Build Status](https://travis-ci.org/mindreframer/callme.png)](https://travis-ci.org/mindreframer/callme) [![Code Climate](https://codeclimate.com/github/mindreframer/callme.png)](https://codeclimate.com/github/mindreframer/callme)
2
+
3
+
4
+
5
+ Callme is an Inversion of Control container for Ruby.
6
+ It takes advantage of the dynamic nature of Ruby to provide a rich and flexible approach to injecting dependencies.
7
+ It's inspired by SpringIoc and tries to give you the same features.
8
+
9
+ ## Usage
10
+ Lets say you have a Logger which has the Appender dependency
11
+
12
+ ```ruby
13
+ class Logger
14
+ attr_accessor :appender
15
+
16
+ def info(message)
17
+ # do some work with appender
18
+ end
19
+ end
20
+
21
+ class Appender
22
+ end
23
+ ```
24
+ To use Logger you need to inject the instance of Appender class, for example
25
+ using setter injection:
26
+ ```ruby
27
+ logger = Logger.new
28
+ logger.appender = Appender.new
29
+ logger.info('some message')
30
+ ```
31
+
32
+ Callme eliminates the manual injection step and injects dependencies by itself.
33
+ To use it you need to instantiate Callme::Container and pass dependency definitions(we call them beans) to it:
34
+ ```ruby
35
+ container = Callme::Container.new do |c|
36
+ c.bean(:appender, class: Appender)
37
+ c.bean(:logger, class: Logger) do
38
+ attr :appender, ref: :appender
39
+ end
40
+ end
41
+ ```
42
+ Now you can get the Logger instance from container with already set dependencies and use it:
43
+ ```ruby
44
+ logger = container[:logger]
45
+ logger.info('some message')
46
+ ```
47
+
48
+ To simplify injection Callme allows you specify dependencies inside of your class:
49
+ ```ruby
50
+ class Logger
51
+ inject :appender
52
+
53
+ def info(message)
54
+ # do some work with appender
55
+ end
56
+ end
57
+
58
+ class Appender
59
+ end
60
+ ```
61
+ With `inject` keyword you won't need to specify class dependencies in bean definition:
62
+ ```ruby
63
+ container = Callme::Container.new do |c|
64
+ c.bean(:appender, class: Appender)
65
+ c.bean(:logger, class: Logger)
66
+ end
67
+ ```
68
+
69
+
70
+
71
+ ## Inheriting from other containers
72
+ Quite often you will want to selectively override some parts of the system, use `Callme::Container.with_parent` to
73
+ create a new container with all the beans copied from the parent container.
74
+
75
+ ```ruby
76
+ class ContactBook
77
+ inject :contacts_repository
78
+ inject :validator, ref: :contact_validator
79
+ end
80
+ class ContactBookService
81
+ inject :contacts_repository
82
+ inject :validator, ref: :contact_validator
83
+ end
84
+ class ContactsRepository
85
+ end
86
+ class ContactValidator
87
+ end
88
+ class TestContactValidator
89
+ end
90
+
91
+ class AnotherTestContactValidator
92
+ end
93
+
94
+ parent = Callme::Container.new do |c|
95
+ c.bean(:contacts_repository, class: ContactsRepository)
96
+ c.bean(:contact_validator, class: ContactValidator)
97
+ c.bean(:contact_book, class: ContactBook)
98
+ c.bean(:contact_book_service, class: "ContactBookService")
99
+ end
100
+ puts parent[:contact_book_service].validator.class
101
+ #=> ContactValidator
102
+
103
+ testcontainer = Callme::Container.with_parent(parent) do |c|
104
+ c.bean(:contact_validator, class: TestContactValidator)
105
+ end
106
+ puts testcontainer[:contact_book_service].validator.class
107
+ #=> TestContactValidator
108
+
109
+ third = Callme::Container.with_parent(parent) do |c|
110
+ c.bean(:contact_validator, class: AnotherTestContactValidator)
111
+ end
112
+
113
+ puts third[:contact_book_service].validator.class
114
+ #=> AnotherTestContactValidator
115
+ ```
116
+
117
+
118
+ ## Installation
119
+
120
+ Add this line to your application's Gemfile:
121
+
122
+ gem 'callme'
123
+
124
+ And then execute:
125
+
126
+ $ bundle
127
+
128
+ Or install it yourself as:
129
+
130
+ $ gem install callme
131
+
132
+ ## Contributing
133
+
134
+ 1. Fork it
135
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
136
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
137
+ 4. Push to the branch (`git push origin my-new-feature`)
138
+ 5. Create new Pull Request
139
+
140
+ # TODO
141
+ 1. Constructor based injection
142
+ 2. Scope registration, refactor BeanFactory. Callme:Container.register_scope(SomeScope)
143
+ 3. Write documentation with more examples
144
+
145
+ ## Author
146
+ Roman Heinrich, [@mindreframer](https://twitter.com/mindreframer)
147
+ Albert Gazizov, [@deeper4k](https://twitter.com/deeper4k)
data/Rakefile ADDED
@@ -0,0 +1 @@
1
+ require "bundler/gem_tasks"
data/bin/console ADDED
@@ -0,0 +1,7 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require "bundler/setup"
4
+ require "callme"
5
+
6
+ require "irb"
7
+ IRB.start(__FILE__)
data/callme.gemspec ADDED
@@ -0,0 +1,24 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'callme/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "callme"
8
+ spec.version = Callme::VERSION
9
+ spec.authors = ["Roman Heinrich", "Albert Gazizov"]
10
+ spec.email = ["roman.heinrich@gmail.com"]
11
+ spec.description = %q{Callme: Simple depencency injection lib}
12
+ spec.summary = %q{Callme: Simple depencency injection lib}
13
+ spec.homepage = "http://github.com/mindreframer/callme"
14
+ spec.license = "MIT"
15
+
16
+ spec.files = `git ls-files`.split($/)
17
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
18
+ spec.test_files = spec.files.grep(%r{^(spec)/})
19
+ spec.require_paths = ["lib"]
20
+
21
+ spec.add_dependency "request_store"
22
+ spec.add_development_dependency "bundler", "~> 1.3"
23
+ spec.add_development_dependency "rake"
24
+ end
@@ -0,0 +1,49 @@
1
+ # Helper class for arguments validation
2
+ module Callme::ArgsValidator
3
+ class << self
4
+
5
+ # Checks that specifid +obj+ is a symbol
6
+ # @param obj some object
7
+ # @param obj_name object's name, used to clarify error causer in exception
8
+ def is_symbol!(obj, obj_name)
9
+ unless obj.is_a?(Symbol)
10
+ raise ArgumentError, "#{obj_name} should be a Symbol"
11
+ end
12
+ end
13
+
14
+ # Checks that specifid +obj+ is an Array
15
+ # @param obj some object
16
+ # @param obj_name object's name, used to clarify error causer in exception
17
+ def is_array!(obj, obj_name)
18
+ unless obj.is_a?(Array)
19
+ raise ArgumentError, "#{obj_name} should be an Array"
20
+ end
21
+ end
22
+
23
+ # Checks that specifid +obj+ is a Hash
24
+ # @param obj some object
25
+ # @param obj_name object's name, used to clarify error causer in exception
26
+ def is_hash!(obj, obj_name)
27
+ unless obj.is_a?(Hash)
28
+ raise ArgumentError, "#{obj_name} should be a Hash"
29
+ end
30
+ end
31
+
32
+ # Checks that specifid +hash+ has a specified +key+
33
+ # @param hash some hash
34
+ # @param key hash's key
35
+ def has_key!(hash, key)
36
+ unless hash.has_key?(key)
37
+ raise ArgumentError, "#{hash} should has #{key} key"
38
+ end
39
+ end
40
+
41
+ # Checks that specified +block+ is given
42
+ # @param block some block
43
+ def block_given!(block)
44
+ unless block
45
+ raise ArgumentError, "Block should be given"
46
+ end
47
+ end
48
+ end
49
+ end
@@ -0,0 +1,115 @@
1
+ require 'callme/scopes'
2
+ require 'callme/scopes/singleton_scope'
3
+ require 'callme/scopes/prototype_scope'
4
+ require 'callme/scopes/request_scope'
5
+
6
+ # Instantiates beans according to their scopes
7
+ class Callme::BeanFactory
8
+ attr_reader :const_loader
9
+
10
+ # Constructor
11
+ # @param beans_metadata_storage [BeansMetadataStorage] storage of bean metadatas
12
+ def initialize(const_loader, beans_metadata_storage)
13
+ @const_loader = const_loader
14
+ @beans_metadata_storage = beans_metadata_storage
15
+ @singleton_scope = Callme::Scopes::SingletonScope.new(self)
16
+ @prototype_scope = Callme::Scopes::PrototypeScope.new(self)
17
+ @request_scope = Callme::Scopes::RequestScope.new(self)
18
+ end
19
+
20
+ # Get bean from the container by it's +name+.
21
+ # According to the bean scope it will be newly created or returned already
22
+ # instantiated bean
23
+ # @param [Symbol] bean name
24
+ # @return bean instance
25
+ # @raise MissingBeanError if bean with the specified name is not found
26
+ def get_bean(name)
27
+ bean_metadata = @beans_metadata_storage.by_name(name)
28
+ unless bean_metadata
29
+ raise Callme::Errors::MissingBeanError, "Bean with name :#{name} is not defined"
30
+ end
31
+ get_bean_with_metadata(bean_metadata)
32
+ end
33
+
34
+ # Get bean by the specified +bean metadata+
35
+ # @param [BeanMetadata] bean metadata
36
+ # @return bean instance
37
+ def get_bean_with_metadata(bean_metadata)
38
+ get_scope_by_metadata(bean_metadata).get_bean(bean_metadata)
39
+ end
40
+
41
+ # Create new bean instance according
42
+ # to the specified +bean_metadata+
43
+ # @param [BeanMetadata] bean metadata
44
+ # @return bean instance
45
+ # @raise MissingBeanError if some of bean dependencies are not found
46
+ def create_bean_and_save(bean_metadata, beans_storage)
47
+ if bean_metadata.bean_class.is_a?(Class)
48
+ bean_class = bean_metadata.bean_class
49
+ else
50
+ bean_class = const_loader.load_const(bean_metadata.bean_class)
51
+ bean_metadata.fetch_attrs!(bean_class)
52
+ end
53
+ bean = bean_metadata.instance ? bean_class.new : bean_class
54
+ if bean_metadata.has_factory_method?
55
+ set_bean_dependencies(bean, bean_metadata)
56
+ bean = bean.send(bean_metadata.factory_method)
57
+ beans_storage[bean_metadata.name] = bean
58
+ else
59
+ # put to container first to prevent circular dependencies
60
+ beans_storage[bean_metadata.name] = bean
61
+ set_bean_dependencies(bean, bean_metadata)
62
+ end
63
+
64
+ bean
65
+ end
66
+
67
+ # Delete bean from the container by it's +name+.
68
+ # @param [Symbol] bean name
69
+ # @raise MissingBeanError if bean with the specified name is not found
70
+ def delete_bean(name)
71
+ bean_metadata = @beans_metadata_storage.by_name(name)
72
+ unless bean_metadata
73
+ raise Callme::Errors::MissingBeanError, "Bean with name :#{name} is not defined"
74
+ end
75
+ get_scope_by_metadata(bean_metadata).delete_bean(bean_metadata)
76
+ end
77
+
78
+ private
79
+
80
+ def set_bean_dependencies(bean, bean_metadata)
81
+ bean_metadata.attrs.each do |attr|
82
+ bean_metadata = @beans_metadata_storage.by_name(attr.ref)
83
+ unless bean_metadata
84
+ raise Callme::Errors::MissingBeanError, "Bean with name :#{attr.ref} is not defined, check #{bean.class}"
85
+ end
86
+ case bean_metadata.scope
87
+ when :singleton
88
+ bean.send("#{attr.name}=", get_bean(attr.ref))
89
+ when :prototype
90
+ bean.instance_variable_set(:@_callme_bean_factory, self)
91
+ bean.define_singleton_method(attr.name) do
92
+ @_callme_bean_factory.get_bean(attr.ref)
93
+ end
94
+ when :request
95
+ bean.instance_variable_set(:@_callme_bean_factory, self)
96
+ bean.define_singleton_method(attr.name) do
97
+ @_callme_bean_factory.get_bean(attr.ref)
98
+ end
99
+ end
100
+ end
101
+ end
102
+
103
+ def get_scope_by_metadata(bean_metadata)
104
+ case bean_metadata.scope
105
+ when :singleton
106
+ @singleton_scope
107
+ when :prototype
108
+ @prototype_scope
109
+ when :request
110
+ @request_scope
111
+ else
112
+ raise Callme::Errors::UnsupportedScopeError, "Bean with name :#{bean_metadata.name} has unsupported scope :#{bean_metadata.scope}"
113
+ end
114
+ end
115
+ end
@@ -0,0 +1,70 @@
1
+ # Stores bean specific data: bean class, name,
2
+ # scope and bean dependencies
3
+ class Callme::BeanMetadata
4
+ attr_reader :name, :bean_class, :scope, :instance, :factory_method, :attrs
5
+
6
+ # Constructor
7
+ # @param name [Symbol] bean name
8
+ # @params options [Hash] includes bean class and scope
9
+ # @params &block [Proc] bean dependencies, has the following structure:
10
+ # do |c|
11
+ # attr :some_dependency, ref: :dependency_name
12
+ # arg :another_dependency, ref: :another_dependency_name
13
+ # end
14
+ # here attr means setter injection, arg means constructon injects
15
+ # +some_dependency+ is an attr_accessor defined in the bean class,
16
+ # +ref+ specifies what dependency from container to use to set the attribute
17
+ def initialize(name, options, &block)
18
+ Callme::ArgsValidator.has_key!(options, :class)
19
+
20
+ @name = name
21
+ @bean_class = options[:class]
22
+ @scope = options[:scope] || :singleton
23
+ @instance = options[:instance].nil? ? true : options[:instance]
24
+ @factory_method = options[:factory_method]
25
+ @attrs = []
26
+
27
+ fetch_attrs!(@bean_class)
28
+
29
+ if block
30
+ Dsl.new(@attrs).instance_exec(&block)
31
+ end
32
+ end
33
+
34
+ def fetch_attrs!(klass)
35
+ if klass.respond_to?(:_callme_injectable_attrs)
36
+ klass._callme_injectable_attrs.each do |attr, options|
37
+ options[:ref] ||= attr
38
+ @attrs << Callme::BeanMetadata::Attribute.new(attr, options)
39
+ end
40
+ end
41
+ end
42
+
43
+ def has_factory_method?
44
+ !!@factory_method
45
+ end
46
+
47
+ class Attribute
48
+ attr_reader :name, :ref
49
+
50
+ def initialize(name, options)
51
+ Callme::ArgsValidator.has_key!(options, :ref)
52
+ @name = name
53
+ @ref = options[:ref]
54
+ end
55
+ end
56
+
57
+ class Dsl
58
+ def initialize(attrs)
59
+ @attrs = attrs
60
+ end
61
+
62
+ def attr(name, options)
63
+ @attrs << Callme::BeanMetadata::Attribute.new(name, options)
64
+ end
65
+
66
+ def arg(name, options)
67
+ @args << Callme::BeanMetadata::Attribute.new(name, options)
68
+ end
69
+ end
70
+ end
@@ -0,0 +1,32 @@
1
+ # Storage of bean metadatas
2
+ class Callme::BeansMetadataStorage
3
+ def initialize(bean_metadatas = {})
4
+ @bean_metadatas = bean_metadatas
5
+ end
6
+
7
+ # Finds bean metadata in storage by it's name
8
+ # @param name [Symbol] bean metadata name
9
+ # @return bean metadata
10
+ def by_name(name)
11
+ @bean_metadatas[name]
12
+ end
13
+
14
+ # Saves a given +bean_metadata+ to the storage
15
+ # @param bean_metadata [BeanMetadata] bean metadata for saving
16
+ def put(bean_metadata)
17
+ @bean_metadatas[bean_metadata.name] = bean_metadata
18
+ end
19
+
20
+ def bean_classes
21
+ @bean_metadatas.values.map(&:bean_class)
22
+ end
23
+
24
+ def keys
25
+ @bean_metadatas.keys
26
+ end
27
+
28
+ # Creates an independent copy of this instance
29
+ def copy
30
+ self.class.new(@bean_metadatas.dup)
31
+ end
32
+ end
@@ -0,0 +1,7 @@
1
+ module Callme::ConstLoaders
2
+ module ActiveSupport
3
+ def self.load_const(const_name)
4
+ ::ActiveSupport::Inflector.constantize(const_name)
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,9 @@
1
+ module Callme::ConstLoaders
2
+ module Native
3
+ def self.load_const(const_name)
4
+ const_name.split('::').inject(Object) do |mod, const_part|
5
+ mod.const_get(const_part)
6
+ end
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,107 @@
1
+ require 'callme/errors'
2
+ require 'callme/args_validator'
3
+ require 'callme/bean_metadata'
4
+ require 'callme/beans_metadata_storage'
5
+ require 'callme/bean_factory'
6
+ require 'callme/const_loaders/native'
7
+
8
+ module Callme
9
+
10
+ # Callme::Container is the central data store for registering objects
11
+ # used for dependency injection. Users register classes by
12
+ # providing a name and a class to create the object(we call them beans). Beans
13
+ # may be retrieved by asking for them by name (via the [] operator)
14
+ class Container
15
+ DEFAULT_CONST_LOADER = Callme::ConstLoaders::Native
16
+
17
+ # Constructor
18
+ # @param resources [Array] array of procs with container's beans definitions
19
+ # @param &block [Proc] optional proc with container's beans definitions
20
+ def initialize(const_loader = DEFAULT_CONST_LOADER, &block)
21
+ @const_loader = const_loader
22
+ @beans_metadata_storage = Callme::BeansMetadataStorage.new
23
+ @bean_factory = Callme::BeanFactory.new(const_loader, @beans_metadata_storage)
24
+
25
+ block.call(self) if block_given?
26
+ end
27
+
28
+ # Evaluates the given array of blocks on the container instance
29
+ # what adds new bean definitions to the container
30
+ # @param resources [Array] array of procs with container's beans definitions
31
+ def self.new_with_beans(resources, const_loader = DEFAULT_CONST_LOADER)
32
+ Callme::ArgsValidator.is_array!(resources, :resources)
33
+
34
+ self.new(const_loader).tap do |container|
35
+ resources.each do |resource|
36
+ resource.call(container)
37
+ end
38
+ end
39
+ end
40
+
41
+ def self.with_parent(parent_container, &block)
42
+ const_loader = parent_container.instance_variable_get("@const_loader")
43
+ beans_metadata_storage = parent_container.instance_variable_get("@beans_metadata_storage").copy
44
+ container = self.new(const_loader)
45
+ container.instance_eval do
46
+ @beans_metadata_storage = beans_metadata_storage
47
+ @bean_factory = Callme::BeanFactory.new(const_loader, beans_metadata_storage)
48
+ end
49
+ block.call(container) if block_given?
50
+ container
51
+ end
52
+
53
+ # Registers new bean in container
54
+ # @param bean_name [Symbol] bean name
55
+ # @param options [Hash] includes bean class and bean scope
56
+ # @param &block [Proc] the block which describes bean dependencies,
57
+ # see more in the BeanMetadata
58
+ def bean(bean_name, options, &block)
59
+ Callme::ArgsValidator.is_symbol!(bean_name, :bean_name)
60
+ Callme::ArgsValidator.is_hash!(options, :options)
61
+
62
+ bean = Callme::BeanMetadata.new(bean_name, options, &block)
63
+ @beans_metadata_storage.put(bean)
64
+ end
65
+
66
+ # Registers new bean in container and replace existing instance if it's instantiated
67
+ # @param bean_name [Symbol] bean name
68
+ # @param options [Hash] includes bean class and bean scope
69
+ # @param &block [Proc] the block which describes bean dependencies,
70
+ # see more in the BeanMetadata
71
+ def replace_bean(bean_name, options, &block)
72
+ if @bean_factory.get_bean(bean_name)
73
+ @bean_factory.delete_bean(bean_name)
74
+ end
75
+ bean(bean_name, options, &block)
76
+ end
77
+
78
+ def reset!
79
+ @bean_factory = Callme::BeanFactory.new(@const_loader, @beans_metadata_storage)
80
+ end
81
+
82
+ # Returns bean instance from the container
83
+ # by the specified bean name
84
+ # @param name [Symbol] bean name
85
+ # @return bean instance
86
+ def [](name)
87
+ Callme::ArgsValidator.is_symbol!(name, :bean_name)
88
+ return @bean_factory.get_bean(name)
89
+ end
90
+
91
+ def keys
92
+ @beans_metadata_storage.keys
93
+ end
94
+
95
+ # Load defined in bean classes
96
+ # this is needed for production usage
97
+ # for eager loading
98
+ def eager_load_bean_classes
99
+ @beans_metadata_storage.bean_classes.each do |bean_class|
100
+ if !bean_class.is_a?(Class)
101
+ @const_loader.load_const(bean_class)
102
+ end
103
+ end
104
+ end
105
+
106
+ end
107
+ end
@@ -0,0 +1,10 @@
1
+ module Callme::Errors
2
+ # Thrown when a service cannot be located by name.
3
+ class MissingBeanError < StandardError; end
4
+
5
+ # Thrown when a duplicate service is registered.
6
+ class DuplicateBeanError < StandardError; end
7
+
8
+ # Thrown when an unsupported bean scope is specified.
9
+ class UnsupportedScopeError < StandardError; end
10
+ end