smart_ioc 0.1.13
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.
- checksums.yaml +7 -0
- data/.gitignore +6 -0
- data/.travis.yml +3 -0
- data/.yardops +1 -0
- data/Gemfile +9 -0
- data/Gemfile.lock +32 -0
- data/LICENSE.txt +22 -0
- data/README.md +91 -0
- data/Rakefile +1 -0
- data/lib/smart_ioc/bean_definition.rb +77 -0
- data/lib/smart_ioc/bean_definitions_storage.rb +79 -0
- data/lib/smart_ioc/bean_dependency.rb +18 -0
- data/lib/smart_ioc/bean_factory.rb +230 -0
- data/lib/smart_ioc/bean_file_loader.rb +26 -0
- data/lib/smart_ioc/bean_locations.rb +71 -0
- data/lib/smart_ioc/bean_locator.rb +32 -0
- data/lib/smart_ioc/container.rb +143 -0
- data/lib/smart_ioc/extra_package_contexts.rb +29 -0
- data/lib/smart_ioc/inject_metadata.rb +13 -0
- data/lib/smart_ioc/iocify.rb +101 -0
- data/lib/smart_ioc/scopes/prototype.rb +26 -0
- data/lib/smart_ioc/scopes/request.rb +35 -0
- data/lib/smart_ioc/scopes/singleton.rb +31 -0
- data/lib/smart_ioc/scopes.rb +2 -0
- data/lib/smart_ioc/version.rb +3 -0
- data/lib/smart_ioc.rb +44 -0
- data/smart_ioc.gemspec +23 -0
- data/spec/smart_ioc/bean_definition_spec.rb +29 -0
- data/spec/smart_ioc/bean_locator_spec.rb +27 -0
- data/spec/smart_ioc/example/admins/repository/admins_dao.rb +20 -0
- data/spec/smart_ioc/example/admins/repository/admins_repository.rb +15 -0
- data/spec/smart_ioc/example/admins/repository/test/admins_repository.rb +17 -0
- data/spec/smart_ioc/example/users/repository/users_dao.rb +17 -0
- data/spec/smart_ioc/example/users/repository/users_repository.rb +16 -0
- data/spec/smart_ioc/example/users/services/users_creator.rb +15 -0
- data/spec/smart_ioc/example/users/user.rb +8 -0
- data/spec/smart_ioc/example/utils/config.rb +15 -0
- data/spec/smart_ioc/example/utils/logger.rb +21 -0
- data/spec/smart_ioc/object_spec.rb +45 -0
- data/spec/smart_ioc/smart_ioc_spec.rb +43 -0
- data/spec/spec_helper.rb +8 -0
- metadata +126 -0
@@ -0,0 +1,32 @@
|
|
1
|
+
class SmartIoC::BeanLocator
|
2
|
+
BEAN_PATTERN = /bean\s+(:[a-zA-z0-9\-\_]+)/
|
3
|
+
|
4
|
+
# @param package_name [Symbol] package name for bean (ex: :repository)
|
5
|
+
# @param dir [String] absolute path for directory with bean definitions
|
6
|
+
# @return nil
|
7
|
+
def locate_beans(package_name, dir)
|
8
|
+
if !package_name.is_a?(Symbol)
|
9
|
+
raise ArgumentError, 'package name should be a symbol'
|
10
|
+
end
|
11
|
+
|
12
|
+
package_name = package_name
|
13
|
+
|
14
|
+
Dir.glob(File.join(dir, '**/*.rb')).each do |file_path|
|
15
|
+
source_str = File.read(file_path)
|
16
|
+
|
17
|
+
beans = find_package_beans(source_str)
|
18
|
+
|
19
|
+
beans.each do |bean_name|
|
20
|
+
SmartIoC::BeanLocations.add_bean(package_name, bean_name, file_path)
|
21
|
+
end
|
22
|
+
end
|
23
|
+
nil
|
24
|
+
end
|
25
|
+
|
26
|
+
private
|
27
|
+
|
28
|
+
def find_package_beans(source_str)
|
29
|
+
tokens = source_str.scan(BEAN_PATTERN)
|
30
|
+
tokens.flatten.uniq.map {|token| token.gsub(':', '').to_sym}
|
31
|
+
end
|
32
|
+
end
|
@@ -0,0 +1,143 @@
|
|
1
|
+
module SmartIoC
|
2
|
+
# SmartIoC::Container is a beans store used for dependency injection
|
3
|
+
class Container
|
4
|
+
DEFAULT_CONTEXT = :default
|
5
|
+
|
6
|
+
class << self
|
7
|
+
def get_instance
|
8
|
+
@container ||= SmartIoC::Container.allocate
|
9
|
+
end
|
10
|
+
|
11
|
+
def clear
|
12
|
+
@container = nil
|
13
|
+
end
|
14
|
+
|
15
|
+
def get_bean(bean_name, package: nil, context: SmartIoC::Container::DEFAULT_CONTEXT)
|
16
|
+
get_instance.get_bean(bean_name, package: package, context: context)
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
def initialize
|
21
|
+
raise ArgumentError, "SmartIoC::Container should not be allocated. Use SmartIoC::Container.get_instance instead"
|
22
|
+
end
|
23
|
+
|
24
|
+
# @param bean_name [Symbol] bean name
|
25
|
+
# @param klass [Class] bean class name
|
26
|
+
# @param path [String] bean file absolute path
|
27
|
+
# @param scope [Symbol] scope value
|
28
|
+
# @param context [Symbol] bean context
|
29
|
+
# @return [SmartIoC::BeanDefinition] bean definition
|
30
|
+
def register_bean(bean_name:, klass:, context:, scope:, path:,
|
31
|
+
factory_method: nil, package_name: nil, instance: true)
|
32
|
+
if !bean_name.is_a?(Symbol)
|
33
|
+
raise ArgumentError, 'bean name should be a Symbol'
|
34
|
+
end
|
35
|
+
|
36
|
+
if !klass.is_a?(Class)
|
37
|
+
raise ArgumentError, 'bean class should be a Class'
|
38
|
+
end
|
39
|
+
|
40
|
+
if !path.is_a?(String)
|
41
|
+
raise ArgumentError, 'path should be a String'
|
42
|
+
end
|
43
|
+
|
44
|
+
if !(instance.is_a?(TrueClass) || instance.is_a?(FalseClass))
|
45
|
+
raise ArgumentError, 'instance should be true or false'
|
46
|
+
end
|
47
|
+
|
48
|
+
if (factory_method && !factory_method.is_a?(Symbol))
|
49
|
+
raise ArgumentError, 'factory method should be a Symbol'
|
50
|
+
end
|
51
|
+
|
52
|
+
context ||= DEFAULT_CONTEXT
|
53
|
+
|
54
|
+
if !context.is_a?(Symbol)
|
55
|
+
raise ArgumentError, 'context should be a Symbol'
|
56
|
+
end
|
57
|
+
|
58
|
+
scope ||= SmartIoC::Scopes::Singleton::VALUE
|
59
|
+
|
60
|
+
allowed_scopes = [
|
61
|
+
SmartIoC::Scopes::Prototype::VALUE,
|
62
|
+
SmartIoC::Scopes::Singleton::VALUE,
|
63
|
+
SmartIoC::Scopes::Request::VALUE
|
64
|
+
]
|
65
|
+
|
66
|
+
if !allowed_scopes.include?(scope)
|
67
|
+
raise ArgumentError, "bean scope should be one of #{allowed_scopes.inspect}"
|
68
|
+
end
|
69
|
+
|
70
|
+
package_name ||= SmartIoC::BeanLocations.get_bean_package(path)
|
71
|
+
|
72
|
+
if !package_name
|
73
|
+
raise ArgumentError, %Q(
|
74
|
+
Package name should be given for bean :#{bean_name}.
|
75
|
+
You should specify package name directly or run
|
76
|
+
|
77
|
+
SmartIoC.find_package_beans(package_name, dir)
|
78
|
+
|
79
|
+
to setup beans before you actually register them.
|
80
|
+
)
|
81
|
+
end
|
82
|
+
|
83
|
+
bean_definition = SmartIoC::BeanDefinition.new(
|
84
|
+
name: bean_name,
|
85
|
+
package: package_name,
|
86
|
+
path: path,
|
87
|
+
klass: klass,
|
88
|
+
instance: instance,
|
89
|
+
factory_method: factory_method,
|
90
|
+
context: context,
|
91
|
+
scope: scope
|
92
|
+
)
|
93
|
+
|
94
|
+
bean_definitions_storage.push(bean_definition)
|
95
|
+
|
96
|
+
bean_definition
|
97
|
+
end
|
98
|
+
|
99
|
+
# Returns bean definition for specific class
|
100
|
+
# @param klass [Class] class name
|
101
|
+
# return [BeanDefinition]
|
102
|
+
def get_bean_definition_by_class(klass)
|
103
|
+
bean_definitions_storage.find_by_class(klass)
|
104
|
+
end
|
105
|
+
|
106
|
+
# Sets extra context for specific package
|
107
|
+
# @param package_name [Symbol] package name
|
108
|
+
# @param context [Symbol] context (ex: :test)
|
109
|
+
def set_extra_context_for_package(package_name, context)
|
110
|
+
extra_package_contexts.set_context(package_name, context)
|
111
|
+
end
|
112
|
+
|
113
|
+
# @param bean_name [Symbol] bean name
|
114
|
+
# @param optional package [Symbol] package name
|
115
|
+
# @param optional context [Symbol] package context
|
116
|
+
# @return bean instance from container
|
117
|
+
def get_bean(bean_name, package: nil, context: SmartIoC::Container::DEFAULT_CONTEXT)
|
118
|
+
bean_factory.get_bean(bean_name, package: package, context: context)
|
119
|
+
end
|
120
|
+
|
121
|
+
def clear_scopes
|
122
|
+
bean_factory.clear_scopes
|
123
|
+
end
|
124
|
+
|
125
|
+
def force_clear_scopes
|
126
|
+
bean_factory.force_clear_scopes
|
127
|
+
end
|
128
|
+
|
129
|
+
private
|
130
|
+
|
131
|
+
def bean_factory
|
132
|
+
@bean_factory ||= SmartIoC::BeanFactory.new(bean_definitions_storage, extra_package_contexts)
|
133
|
+
end
|
134
|
+
|
135
|
+
def extra_package_contexts
|
136
|
+
@extra_package_contexts ||= SmartIoC::ExtraPackageContexts.new
|
137
|
+
end
|
138
|
+
|
139
|
+
def bean_definitions_storage
|
140
|
+
@bean_definitions_storage ||= SmartIoC::BeanDefinitionsStorage.new
|
141
|
+
end
|
142
|
+
end
|
143
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
class SmartIoC::ExtraPackageContexts
|
2
|
+
def initialize
|
3
|
+
@data = {}
|
4
|
+
end
|
5
|
+
|
6
|
+
# @param package_name [Symbol]
|
7
|
+
# @param context [Symbol]
|
8
|
+
def set_context(package_name, context)
|
9
|
+
if !package_name.is_a?(Symbol)
|
10
|
+
raise ArgumentError, "package name should be a Symbol"
|
11
|
+
end
|
12
|
+
|
13
|
+
if !context.is_a?(Symbol)
|
14
|
+
raise ArgumentError, "context should be a Symbol"
|
15
|
+
end
|
16
|
+
|
17
|
+
@data[package_name] = context
|
18
|
+
end
|
19
|
+
|
20
|
+
def get_context(package_name)
|
21
|
+
@data[package_name] || SmartIoC::Container::DEFAULT_CONTEXT
|
22
|
+
end
|
23
|
+
|
24
|
+
# @param package_name [Symbol]
|
25
|
+
def clear_context(package_name)
|
26
|
+
@data.delete(package_name)
|
27
|
+
nil
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,101 @@
|
|
1
|
+
# Extend Object with bean declaration and bean injection functionality
|
2
|
+
# Example of usage:
|
3
|
+
# class Bar
|
4
|
+
# bean :bar
|
5
|
+
# end
|
6
|
+
#
|
7
|
+
# class Foo
|
8
|
+
# include SmartIoC::Iocify
|
9
|
+
# bean :foo, scope: :prototype, instance: false, factory_method: :get_beans
|
10
|
+
#
|
11
|
+
# inject :bar
|
12
|
+
# inject :some_bar, ref: bar, from: :repository
|
13
|
+
#
|
14
|
+
# def hello_world
|
15
|
+
# puts 'Hello world'
|
16
|
+
# end
|
17
|
+
# end
|
18
|
+
#
|
19
|
+
# SmartIoC::Container.get_bean(:bar).hello_world
|
20
|
+
module SmartIoC::Iocify
|
21
|
+
def self.included base
|
22
|
+
base.extend ClassMethods
|
23
|
+
end
|
24
|
+
|
25
|
+
module ClassMethods
|
26
|
+
# @param bean_name [Symbol] bean name
|
27
|
+
# @param scope [Symbol] bean scope (defaults to :singleton)
|
28
|
+
# @param package [nil or Symbol]
|
29
|
+
# @param factory_method [nil or Symbol] factory method to get bean
|
30
|
+
# @param instance [Boolean] instance based bean or class-based
|
31
|
+
# @param context [Symbol] set bean context (ex: :test)
|
32
|
+
# @return nil
|
33
|
+
def bean(bean_name, scope: nil, package: nil, instance: true, factory_method: nil, context: nil)
|
34
|
+
file_path = caller[0].split(':').first
|
35
|
+
|
36
|
+
bean_definition = SmartIoC::Container.get_instance.get_bean_definition_by_class(self)
|
37
|
+
|
38
|
+
# skip if bean was registered
|
39
|
+
return if bean_definition
|
40
|
+
|
41
|
+
bean_definition = SmartIoC::Container.get_instance.register_bean(
|
42
|
+
bean_name: bean_name,
|
43
|
+
klass: self,
|
44
|
+
scope: scope,
|
45
|
+
path: file_path,
|
46
|
+
package_name: package,
|
47
|
+
instance: instance,
|
48
|
+
factory_method: factory_method,
|
49
|
+
context: context
|
50
|
+
)
|
51
|
+
|
52
|
+
if bean_definition.is_instance?
|
53
|
+
class_eval %Q(
|
54
|
+
def initialize
|
55
|
+
raise ArgumentError, "constructor based allocation is not allowed for beans. Use ioc container to allocate bean."
|
56
|
+
end
|
57
|
+
)
|
58
|
+
end
|
59
|
+
|
60
|
+
nil
|
61
|
+
end
|
62
|
+
|
63
|
+
# @param bean_name [Symbol] injected bean name
|
64
|
+
# @param ref [Symbol] refferece bean to be sef as bean_name
|
65
|
+
# @param from [Symbol] package name
|
66
|
+
# @return nil
|
67
|
+
# @raise [ArgumentError] if bean_name is not a Symbol
|
68
|
+
# @raise [ArgumentError] if ref provided and ref is not a Symbol
|
69
|
+
# @raise [ArgumentError] if from provided and from is not a Symbol
|
70
|
+
# @raise [ArgumentError] if bean with same name was injected before
|
71
|
+
def inject(bean_name, ref: nil, from: nil)
|
72
|
+
bean_definition = SmartIoC::Container.get_instance.get_bean_definition_by_class(self)
|
73
|
+
|
74
|
+
if bean_definition.nil?
|
75
|
+
raise ArgumentError, "current class is not registered as bean. Add bean :bean_name declaration"
|
76
|
+
end
|
77
|
+
|
78
|
+
bean_definition.add_dependency(
|
79
|
+
bean_name: bean_name,
|
80
|
+
ref: ref,
|
81
|
+
package: from
|
82
|
+
)
|
83
|
+
|
84
|
+
if bean_definition.is_instance?
|
85
|
+
class_eval %Q(
|
86
|
+
private
|
87
|
+
attr_reader :#{bean_name}
|
88
|
+
)
|
89
|
+
else
|
90
|
+
class_eval %Q(
|
91
|
+
class << self
|
92
|
+
private
|
93
|
+
attr_reader :#{bean_name}
|
94
|
+
end
|
95
|
+
)
|
96
|
+
end
|
97
|
+
|
98
|
+
nil
|
99
|
+
end
|
100
|
+
end
|
101
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
# Prototype scope instantiates new bean instance on each call
|
2
|
+
class SmartIoC::Scopes::Prototype
|
3
|
+
VALUE = :prototype
|
4
|
+
|
5
|
+
# Get new bean instance
|
6
|
+
# @param bean_definition [BeanDefinition] bean definition
|
7
|
+
# @returns nil
|
8
|
+
def get_bean(bean_definition)
|
9
|
+
# do nothing
|
10
|
+
end
|
11
|
+
|
12
|
+
# @param klass [Class] bean class
|
13
|
+
# @param bean [Any Object] bean object
|
14
|
+
# @returns nil
|
15
|
+
def save_bean(klass, bean)
|
16
|
+
# do nothing
|
17
|
+
end
|
18
|
+
|
19
|
+
def clear
|
20
|
+
# do nothing
|
21
|
+
end
|
22
|
+
|
23
|
+
def force_clear
|
24
|
+
# do nothing
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
# Request scope instantiates new bean instance if it's not present in Thread.current
|
2
|
+
class SmartIoC::Scopes::Request < SmartIoC::Scopes::Singleton
|
3
|
+
VALUE = :request
|
4
|
+
KEY = :__SmartIoC
|
5
|
+
|
6
|
+
# @param bean_factory bean factory
|
7
|
+
def initialize
|
8
|
+
clear
|
9
|
+
end
|
10
|
+
|
11
|
+
|
12
|
+
# @param klass [Class] bean class
|
13
|
+
# @returns bean instance or nil if not stored
|
14
|
+
def get_bean(klass)
|
15
|
+
@beans[klass]
|
16
|
+
end
|
17
|
+
|
18
|
+
# @param klass [Class] bean class
|
19
|
+
# @param bean [Any Object] bean object
|
20
|
+
# @returns nil
|
21
|
+
def save_bean(klass, bean)
|
22
|
+
@beans[klass] = bean
|
23
|
+
nil
|
24
|
+
end
|
25
|
+
|
26
|
+
def clear
|
27
|
+
Thread.current[KEY] = {}
|
28
|
+
@beans = Thread.current[KEY]
|
29
|
+
nil
|
30
|
+
end
|
31
|
+
|
32
|
+
def force_clear
|
33
|
+
clear
|
34
|
+
end
|
35
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
# Singleton scope returns same bean instance on each call
|
2
|
+
class SmartIoC::Scopes::Singleton
|
3
|
+
VALUE = :singleton
|
4
|
+
|
5
|
+
def initialize
|
6
|
+
@beans = {}
|
7
|
+
end
|
8
|
+
|
9
|
+
# @param klass [Class] bean class
|
10
|
+
# @returns bean instance or nil if not stored
|
11
|
+
def get_bean(klass)
|
12
|
+
@beans[klass]
|
13
|
+
end
|
14
|
+
|
15
|
+
# @param klass [Class] bean class
|
16
|
+
# @param bean [Any Object] bean object
|
17
|
+
# @returns nil
|
18
|
+
def save_bean(klass, bean)
|
19
|
+
@beans[klass] = bean
|
20
|
+
nil
|
21
|
+
end
|
22
|
+
|
23
|
+
def clear
|
24
|
+
# do nothing as singleton beans are being instantiated only once
|
25
|
+
end
|
26
|
+
|
27
|
+
def force_clear
|
28
|
+
@beans = {}
|
29
|
+
nil
|
30
|
+
end
|
31
|
+
end
|
data/lib/smart_ioc.rb
ADDED
@@ -0,0 +1,44 @@
|
|
1
|
+
require 'smart_ioc/version'
|
2
|
+
|
3
|
+
module SmartIoC
|
4
|
+
autoload :BeanDefinition, 'smart_ioc/bean_definition'
|
5
|
+
autoload :BeanDefinitionsStorage, 'smart_ioc/bean_definitions_storage'
|
6
|
+
autoload :BeanDependency, 'smart_ioc/bean_dependency'
|
7
|
+
autoload :BeanFactory, 'smart_ioc/bean_factory'
|
8
|
+
autoload :BeanFileLoader, 'smart_ioc/bean_file_loader'
|
9
|
+
autoload :BeanLocations, 'smart_ioc/bean_locations'
|
10
|
+
autoload :BeanLocator, 'smart_ioc/bean_locator'
|
11
|
+
autoload :Container, 'smart_ioc/container'
|
12
|
+
autoload :ExtraPackageContexts, 'smart_ioc/extra_package_contexts'
|
13
|
+
autoload :InjectMetadata, 'smart_ioc/inject_metadata'
|
14
|
+
autoload :Iocify, 'smart_ioc/iocify'
|
15
|
+
autoload :Scopes, 'smart_ioc/scopes'
|
16
|
+
|
17
|
+
module Scopes
|
18
|
+
autoload :Prototype, 'smart_ioc/scopes/prototype'
|
19
|
+
autoload :Singleton, 'smart_ioc/scopes/singleton'
|
20
|
+
autoload :Request, 'smart_ioc/scopes/request'
|
21
|
+
end
|
22
|
+
|
23
|
+
class << self
|
24
|
+
# @param package_name [String or Symbol] package name for bean definitions
|
25
|
+
# @param dir [String] absolute path with bean definitions
|
26
|
+
# @return nil
|
27
|
+
def find_package_beans(package_name, dir)
|
28
|
+
bean_locator = SmartIoC::BeanLocator.new
|
29
|
+
bean_locator.locate_beans(package_name.to_sym, dir)
|
30
|
+
nil
|
31
|
+
end
|
32
|
+
|
33
|
+
# Load all beans (usually required for production env)
|
34
|
+
def load_all_beans
|
35
|
+
SmartIoC::BeanLocations.load_all
|
36
|
+
end
|
37
|
+
|
38
|
+
# Full clear of data (mostly for tests)
|
39
|
+
def clear
|
40
|
+
SmartIoC::BeanLocations.clear
|
41
|
+
SmartIoC::Container.clear
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
data/smart_ioc.gemspec
ADDED
@@ -0,0 +1,23 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'smart_ioc/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = "smart_ioc"
|
8
|
+
spec.version = SmartIoC::VERSION
|
9
|
+
spec.authors = ["Ruslan Gatiyatov"]
|
10
|
+
spec.email = ["ruslan@droidlabs.pro"]
|
11
|
+
spec.description = %q{Inversion of Control Container}
|
12
|
+
spec.summary = %q{Inversion of Control Container}
|
13
|
+
spec.homepage = "http://github.com/droidlabs/smart_ioc"
|
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_development_dependency 'bundler', '~> 1.3'
|
22
|
+
spec.add_development_dependency 'rake'
|
23
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe SmartIoC::BeanDefinition do
|
4
|
+
describe "::inspect" do
|
5
|
+
it {
|
6
|
+
bd = SmartIoC::BeanDefinition.new(
|
7
|
+
name: :test_bean,
|
8
|
+
package: :test_package,
|
9
|
+
path: 'current_dir',
|
10
|
+
klass: Object,
|
11
|
+
scope: :singleton,
|
12
|
+
context: :default,
|
13
|
+
instance: false,
|
14
|
+
factory_method: nil
|
15
|
+
)
|
16
|
+
|
17
|
+
str =
|
18
|
+
"class: Object
|
19
|
+
name: :test_bean
|
20
|
+
package: :test_package
|
21
|
+
context: :default
|
22
|
+
path: current_dir
|
23
|
+
instance: false
|
24
|
+
factory_method: "
|
25
|
+
|
26
|
+
expect(bd.inspect).to eq(str)
|
27
|
+
}
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe SmartIoC::BeanLocator do
|
4
|
+
before :all do
|
5
|
+
SmartIoC.clear
|
6
|
+
|
7
|
+
locator = SmartIoC::BeanLocator.new
|
8
|
+
current_dir = File.expand_path(File.dirname(__FILE__))
|
9
|
+
locator.locate_beans(:test, File.join(current_dir, 'example'))
|
10
|
+
end
|
11
|
+
|
12
|
+
it {
|
13
|
+
locations = SmartIoC::BeanLocations.get_bean_locations(:repository)
|
14
|
+
|
15
|
+
expect(locations[:test].size).to eq(3)
|
16
|
+
expect(locations[:test][0]).to match(/example\/admins\/repository\/admins_repository.rb/)
|
17
|
+
expect(locations[:test][1]).to match(/example\/admins\/repository\/test\/admins_repository.rb/)
|
18
|
+
expect(locations[:test][2]).to match(/example\/users\/repository\/users_repository.rb/)
|
19
|
+
}
|
20
|
+
|
21
|
+
it {
|
22
|
+
locations = SmartIoC::BeanLocations.get_bean_locations(:users_creator)
|
23
|
+
|
24
|
+
expect(locations[:test].size).to eq(1)
|
25
|
+
expect(locations[:test].first).to match(/example\/users\/services\/users_creator.rb/)
|
26
|
+
}
|
27
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
class AdminsDAO
|
2
|
+
include SmartIoC::Iocify
|
3
|
+
|
4
|
+
bean :dao, instance: false
|
5
|
+
|
6
|
+
inject :config
|
7
|
+
|
8
|
+
@data = {}
|
9
|
+
|
10
|
+
class << self
|
11
|
+
def insert(entity)
|
12
|
+
config.app_name
|
13
|
+
@data[entity.id] = entity
|
14
|
+
end
|
15
|
+
|
16
|
+
def get(id)
|
17
|
+
@data[id]
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
class UsersRepository
|
2
|
+
include SmartIoC::Iocify
|
3
|
+
|
4
|
+
bean :repository
|
5
|
+
|
6
|
+
inject :users_creator # just for testing purposes (circular load check)
|
7
|
+
inject :dao
|
8
|
+
|
9
|
+
def put(user)
|
10
|
+
dao.insert(user)
|
11
|
+
end
|
12
|
+
|
13
|
+
def get(id)
|
14
|
+
dao.get(id)
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
require_relative '../user'
|
2
|
+
|
3
|
+
class UsersCreator
|
4
|
+
include SmartIoC::Iocify
|
5
|
+
|
6
|
+
bean :users_creator
|
7
|
+
|
8
|
+
inject :repository, from: :admins
|
9
|
+
inject :logger
|
10
|
+
|
11
|
+
def create(id, email)
|
12
|
+
user = User.new(id, email)
|
13
|
+
repository.put(user)
|
14
|
+
end
|
15
|
+
end
|