smart_ioc 0.1.13
Sign up to get free protection for your applications and to get access to all the features.
- 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
|