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.
Files changed (42) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +6 -0
  3. data/.travis.yml +3 -0
  4. data/.yardops +1 -0
  5. data/Gemfile +9 -0
  6. data/Gemfile.lock +32 -0
  7. data/LICENSE.txt +22 -0
  8. data/README.md +91 -0
  9. data/Rakefile +1 -0
  10. data/lib/smart_ioc/bean_definition.rb +77 -0
  11. data/lib/smart_ioc/bean_definitions_storage.rb +79 -0
  12. data/lib/smart_ioc/bean_dependency.rb +18 -0
  13. data/lib/smart_ioc/bean_factory.rb +230 -0
  14. data/lib/smart_ioc/bean_file_loader.rb +26 -0
  15. data/lib/smart_ioc/bean_locations.rb +71 -0
  16. data/lib/smart_ioc/bean_locator.rb +32 -0
  17. data/lib/smart_ioc/container.rb +143 -0
  18. data/lib/smart_ioc/extra_package_contexts.rb +29 -0
  19. data/lib/smart_ioc/inject_metadata.rb +13 -0
  20. data/lib/smart_ioc/iocify.rb +101 -0
  21. data/lib/smart_ioc/scopes/prototype.rb +26 -0
  22. data/lib/smart_ioc/scopes/request.rb +35 -0
  23. data/lib/smart_ioc/scopes/singleton.rb +31 -0
  24. data/lib/smart_ioc/scopes.rb +2 -0
  25. data/lib/smart_ioc/version.rb +3 -0
  26. data/lib/smart_ioc.rb +44 -0
  27. data/smart_ioc.gemspec +23 -0
  28. data/spec/smart_ioc/bean_definition_spec.rb +29 -0
  29. data/spec/smart_ioc/bean_locator_spec.rb +27 -0
  30. data/spec/smart_ioc/example/admins/repository/admins_dao.rb +20 -0
  31. data/spec/smart_ioc/example/admins/repository/admins_repository.rb +15 -0
  32. data/spec/smart_ioc/example/admins/repository/test/admins_repository.rb +17 -0
  33. data/spec/smart_ioc/example/users/repository/users_dao.rb +17 -0
  34. data/spec/smart_ioc/example/users/repository/users_repository.rb +16 -0
  35. data/spec/smart_ioc/example/users/services/users_creator.rb +15 -0
  36. data/spec/smart_ioc/example/users/user.rb +8 -0
  37. data/spec/smart_ioc/example/utils/config.rb +15 -0
  38. data/spec/smart_ioc/example/utils/logger.rb +21 -0
  39. data/spec/smart_ioc/object_spec.rb +45 -0
  40. data/spec/smart_ioc/smart_ioc_spec.rb +43 -0
  41. data/spec/spec_helper.rb +8 -0
  42. 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,13 @@
1
+ class SmartIoC::InjectMetadata
2
+ attr_reader :bean, :ref, :from
3
+
4
+ def initialize(bean, ref, from)
5
+ @bean = bean
6
+ @ref = ref
7
+ @from = from
8
+ end
9
+
10
+ def ref
11
+ @ref || @bean
12
+ end
13
+ 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
@@ -0,0 +1,2 @@
1
+ module SmartIoC::Scopes
2
+ end
@@ -0,0 +1,3 @@
1
+ module SmartIoC
2
+ VERSION = "0.1.13"
3
+ 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,15 @@
1
+ class AdminsRepository
2
+ include SmartIoC::Iocify
3
+
4
+ bean :repository
5
+
6
+ inject :dao
7
+
8
+ def put(user)
9
+ dao.insert(user)
10
+ end
11
+
12
+ def get(id)
13
+ dao.get(id)
14
+ end
15
+ end
@@ -0,0 +1,17 @@
1
+ class TestAdminsRepository
2
+ include SmartIoC::Iocify
3
+
4
+ bean :repository, context: :test, instance: false
5
+
6
+ @data = {}
7
+
8
+ class << self
9
+ def put(user)
10
+ @data[user.id] = user
11
+ end
12
+
13
+ def get(id)
14
+ @data[id]
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,17 @@
1
+ class UsersDAO
2
+ include SmartIoC::Iocify
3
+
4
+ bean :dao, instance: false
5
+
6
+ @data = {}
7
+
8
+ class << self
9
+ def insert(entity)
10
+ @data[entity.id] = entity
11
+ end
12
+
13
+ def get(id)
14
+ @data[id]
15
+ end
16
+ end
17
+ 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
@@ -0,0 +1,8 @@
1
+ class User
2
+ attr_reader :id, :email
3
+
4
+ def initialize(id, email)
5
+ @id = id
6
+ @email = email
7
+ end
8
+ end
@@ -0,0 +1,15 @@
1
+ class Config
2
+ include SmartIoC::Iocify
3
+
4
+ bean :config, factory_method: :get_config
5
+
6
+ class TestConfig
7
+ def app_name
8
+ 'SmartIoC'
9
+ end
10
+ end
11
+
12
+ def get_config
13
+ TestConfig.new
14
+ end
15
+ end