micon 0.1.19 → 0.1.20

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 (4) hide show
  1. data/Rakefile +1 -1
  2. data/lib/micon.rb +3 -1
  3. data/readme.md +116 -140
  4. metadata +3 -3
data/Rakefile CHANGED
@@ -3,7 +3,7 @@ require 'rake_ext'
3
3
  project(
4
4
  name: "micon",
5
5
  gem: true,
6
- summary: "Micon IoC assembles and manages Your Application",
6
+ summary: "Silent and invisible Killer of dependencies and configs",
7
7
 
8
8
  author: "Alexey Petrushin",
9
9
  homepage: "http://github.com/alexeypetrushin/micon"
data/lib/micon.rb CHANGED
@@ -18,4 +18,6 @@ end
18
18
  # Initializing Micon
19
19
  Micon::Core.send :include, Micon::Helper
20
20
  micon = Micon::Core.new
21
- micon.initialize!
21
+ micon.initialize!
22
+
23
+ def micon; ::MICON end unless $dont_create_micon_shortcut
data/readme.md CHANGED
@@ -1,177 +1,154 @@
1
- # Micon IoC assembles and manages Your Application
1
+ # Micon - silent and invisible Killer of dependencies and configs
2
2
 
3
- Micon is infrastructural component, invisible to user and it's main goal is to simplify development. It reduces complex monolithic application to set of simple low coupled components.
3
+ Micon allows You easilly and transparently eliminate dependencies and configs in Your Application. Usually, when You are building complex system there are following tasks should be solved:
4
4
 
5
- Concentrate on business logic and interfaces and Micon will provide automatic configuration, life cycle management and dependency resolving.
5
+ - where the component's code is located
6
+ - in what order should it be loaded
7
+ - what configs does the component needs to be properly initialized
8
+ - where those configs are stored
9
+ - how to change configs in different environments
10
+ - where are dependencies for component and how they should be initialized
11
+ - how to replace some components with custom implementation
12
+ - how to assembly parts of application for specs/tests
13
+ - how to restore state after each spec/test (isolate it from each other)
14
+ - how to control life-cycle of dynamically created components
15
+ - connecting components to assemble an application
6
16
 
7
- Technically it's [IoC][ioc] like framework with components, callbacks, scopes and bijections, inspired by Spring and JBoss Seam.
17
+ *By component I mean any parts of code logically grouped together.*
8
18
 
9
- Is it usefull, is there any real-life application? - I'm using it as a heart of my [web framework][rad_core], this sites http://robotigra.ru, http://ruby-lang.info for example powered with it.
19
+ Micon **solves all these tasks automatically**, and has the following **price** - You has to:
10
20
 
11
- ## Usage
21
+ - use the *register component_name, &initialization_block* method for component initialization
22
+ - use the *inject component_name* to whire components toghether
23
+ - place component definition to the lib/components folder
12
24
 
13
- Let's suppose you are building the Ruby on Rails clone, there are lots of modules let's try to deal with them
25
+ That's all the price, not a big one, compared to the value, eh?
26
+ That all You need to know to use 95% of it, there are also 2-3 more specific methods, but they are needed very rarelly.
14
27
 
15
- ``` ruby
16
- # Let's suppose that we want to build the Rails clone,
17
- # there will be lot's of components - logger, controllers, router, ...
28
+ Techincally Micon is sort of Dependency Injector, but because of it's simplicity and invisibility it looks like an alien compared to it's complex and bloated IoC / DI cousins.
29
+
30
+ ## Basic example
18
31
 
32
+ ``` ruby
19
33
  require 'micon'
34
+ # standard ruby logger
35
+ require 'logger'
20
36
 
21
- # Handy shortcut to access the IoC API (this is optional and You can omit it).
22
- def micon; MICON end
37
+ micon.register(:logger){Logger.new}
23
38
 
24
- # Let's define some components.
25
- # The :logger is one per application, it's a static component (like singleton).
26
- class Logger
27
- register_as :logger
28
- attr_accessor :log_file_path
29
- def info msg
30
- puts "#{msg} (writen to #{log_file_path})" unless defined?(RSpec)
39
+ class Application
40
+ inject logger: :logger
41
+
42
+ def run
43
+ logger.info 'running ...'
31
44
  end
32
45
  end
33
46
 
34
- # To demostrate basics of working with compnents let's configure our :logger
35
- # explicitly (in the next example, it will be configured automatically).
36
- micon.logger.log_file_path = '/tmp/web_framework.log'
37
-
38
- # The :router requires complex initialization, so we use
39
- # another form of component registration.
40
- class Router
41
- def initialize routes; @routes = routes end
42
- def decode request;
43
- class_name, method = @routes[request.url]
44
- return eval(class_name), method # returning actual class
45
- end
46
- end
47
- micon.register :router do
48
- Router.new '/index' => ['PagesController', :index]
49
- end
47
+ Application.new.run # => running ...
48
+ ```
50
49
 
51
- # The :controller component should be created and destroyed dynamically,
52
- # for each request, we specifying that component is dynamic
53
- # by declaring it's :scope.
54
- # And, we don't know beforehead what it actully will be, for different
55
- # request there can be different controllers,
56
- # so, here we just declaring it without any initialization block, it
57
- # will be created at runtime later.
58
- micon.register :controller, scope: :request
59
-
60
- # Let's define some of our controllers, the PagesController, note - we
61
- # don't register it as component.
62
- class PagesController
63
- # We need access to :logger and :request, let's inject them
64
- inject logger: :logger, request: :request
65
-
66
- def index
67
- # Here we can use injected component
68
- logger.info "Application: processing #{request}"
69
- end
70
- end
50
+ Code in examples/basics.rb
71
51
 
72
- # Request is also dynamic, and it also can't be created beforehead.
73
- # We also registering it without initialization, it will be
74
- # created at runtime later.
75
- class Request
76
- attr_reader :url
77
- def initialize url; @url = url end
78
- def to_s; @url end
79
- end
80
- # Registering without initialization block.
81
- micon.register :request, scope: :request
82
-
83
- # We need to integrate our application with web server, for example with the Rack.
84
- # When the server receive web request, it calls the :call method of our RackAdapter
85
- class RackAdapter
86
- # Injecting components
87
- inject request: :request, controller: :controller
88
-
89
- def call env
90
- # We need to tell Micon that the :request scope is started, so it will know
91
- # that some dynamic components should be created during this scope and
92
- # destroyed at the end of it.
93
- micon.activate :request, {} do
94
- # Here we manually creating the Request component
95
- self.request = Request.new '/index'
52
+ ## Advanced example: let's build the Ultima - an Ultimate Web Framework
53
+
54
+ This example is more complicated and requires about 3-7 minutes.
55
+
56
+ Let's pretend that we are building an Ultimate Framework, the RoR Killer. There will be lot's of modules and dependencies, let's see how Micon can eliminate them.
57
+ There will be two steps, at the first we'll build it as usual, and at the second refactor it using Micon.
96
58
 
97
- # The :router also can be injected via :inject,
98
- # but we can also use another way to access components,
99
- # every component also availiable as micon.<component_name>
100
- controller_class, method = micon.router.decode request
59
+ There will be following components: router, request.
101
60
 
102
- # Let's create and call our controller
103
- self.controller = controller_class.new
61
+ ``` ruby
62
+ # Assembling Ultima Framework
63
+ module Ultima
64
+ class << self
65
+ attr_accessor :router, :config
66
+
67
+ def run url
68
+ request = Request.new url
69
+
70
+ controller_class, method = router.decode url
71
+
72
+ controller = controller_class.new
73
+ controller.request = request
104
74
  controller.send method
105
75
  end
106
76
  end
107
77
  end
108
78
 
109
- # Let's pretend that there's a Web Server and run our application,
79
+ require 'yaml'
80
+ Ultima.config = YAML.load_file "#{dir}/config/config.yml"
81
+
82
+ require 'router'
83
+ router = Router.new
84
+ router.url_root = Ultima.config['url_root']
85
+ Ultima.router = router
86
+
87
+ require 'request'
88
+ require 'controller'
89
+
90
+
91
+ # Assemblilng Application
92
+ require 'pages_controller'
93
+
94
+ Ultima.router.add_route '/index', PagesController, :index
95
+
96
+
97
+ # Let's run it
98
+ Ultima.run '/index'
110
99
  # You should see something like this in the console:
111
- # Application: processing /index
112
- RackAdapter.new.call({})
100
+ # PagesController: displaying the :index page.
113
101
  ```
114
102
 
115
- The example above is a good way to demonstrate how the IoC works in general, but it will not show two **extremelly important** aspects of IoC: **auto-discovery** and **auto-configuration**.
116
- In real-life scenario You probably will use it in a little different way, as will be shown below, and utilize these important features (there's a short article about why these features are important [You underestimate the power of IoC][article]).
103
+ Code in examples/ultima1/run.rb
104
+
105
+ Below are the same example but done with Micon. As You can see there's no any assembling or configuration code, because all the components are auto-discovered, auto-loaded and auto-configured.
106
+
107
+ ``` ruby
108
+ # Assembling Ultima Framework
109
+ # All components: router, request, controller will be automatically loaded & configured.
110
+ class Ultima
111
+ inject router: :router
112
+
113
+ def run url
114
+ # we need to tell Micon about the :request scope, so the Request will be
115
+ # created & destroyed during this scope automatically.
116
+ micon.activate :request, {} do
117
+ request = Request.new url
118
+
119
+ controller_class, method = router.decode url
120
+
121
+ controller = controller_class.new
122
+ # no need to explicitly set request, it will be automatically injected
123
+ controller.send method
124
+ end
125
+ end
126
+ end
127
+ micon.register(:ultima){Ultima.new}
128
+
129
+ # No need for 'requre', all classes will be discowered & laoded automatically
117
130
 
118
- I would like to repeat it one more time - **auto-discovery and auto-configuration is extremelly important features** of the IoC, don't ignore them.
131
+ # No need for config, Micon will automatically discower config/router.yml
119
132
 
120
- Below are the same example but done with utilizing these features, this is how the Micon IoC is supposed be used in the real-life scenario. As You can see it's almost empty, because all the components are auto-discovered, auto-loaded and auto-configured. Components are located in the [examples/web_framework2/lib/components](https://github.com/alexeypetrushin/micon/blob/master/examples/web_framework2/lib/components) folder.
133
+ # No need for manual router configuring, router.yml config will be applied automatically
121
134
 
122
- Note also, that this time logger convigured automatically, with the logger.yml configuration file.
123
135
 
124
- ``` ruby
125
- # Please examine the 'web_framework1.rb' example before proceeding with this one.
136
+ # Assemblilng Application
137
+ # Controller will be loaded automatically
138
+ micon.router.add_route '/index', PagesController, :index
126
139
 
127
- # Let's suppose that we want to build the Rails clone,
128
- # there will be lot's of components - logger, controllers, router, ...
129
140
 
130
- # In this example we also need another tool that automatically find & load classes.
131
- require 'micon'
132
- require 'class_loader'
133
-
134
- # Handy shortcut to access the IoC API (this is optional and You can omit it).
135
- def micon; MICON end
136
-
137
- # Auto-discovering:
138
- #
139
- # All components (:logger, :router, :request, :controller) are defined in
140
- # the web_framework2/lib/components folder.
141
- # All classes (PagesController, RackAdapter) are
142
- # located in web_framework2/lib folder.
143
- #
144
- # Note that there will be no any "require 'xxx'" clause, all components and
145
- # classes will be loaded and dependecies be resolved automatically.
146
-
147
- # Adding libraries to load path (in order to load components automatically).
148
- lib_dir = "#{File.dirname(__FILE__)}/web_framework2/lib"
149
- $LOAD_PATH << lib_dir
150
-
151
- # Adding libraries to autoload path (in order to load classes automatically).
152
- autoload_path lib_dir
153
-
154
- # Auto-configuring
155
- #
156
- # Remember our manual configuration of "logger.log_file_path" from
157
- # the previous example?
158
- # This time it will be configured automatically, take a look at
159
- # the web_framework2/lib/components/logger.yml file.
160
- #
161
- # Note, that there are also logger.production.yml, Micon is smart
162
- # and will merge configs in the following order:
163
- # logger.yml <- logger.<env>.yml <- <runtime_path>/config/logger.yml
164
- # (If you define :environment and :runtime_path variables).
165
-
166
- # Let's pretend that there's a Web Server and run our application,
141
+ # Let's run it
142
+ micon.ultima.run '/index'
167
143
  # You should see something like this in the console:
168
- # Application: processing /index
169
- RackAdapter.new.call({})
144
+ # PagesController: displaying the :index page.
170
145
  ```
171
146
 
172
- For the actual code please look at [examples](https://github.com/alexeypetrushin/micon/blob/master/examples).
147
+ Code in examples/ultima2/run.rb
148
+
149
+ ## More samples
173
150
 
174
- If You are interested in more samples, please look at the [actual components][rad_core_components] used in the Rad Core Framework.
151
+ If You are interested in more samples, please take a look at the [actual components][rad_core_components] used in the Rad Core Web Framework.
175
152
 
176
153
  ## Note
177
154
 
@@ -190,5 +167,4 @@ Copyright (c) Alexey Petrushin http://petrush.in, released under the MIT license
190
167
 
191
168
  [ioc]: http://en.wikipedia.org/wiki/Inversion_of_control
192
169
  [rad_core]: https://github.com/alexeypetrushin/rad_core
193
- [rad_core_components]: https://github.com/alexeypetrushin/rad_core/tree/master/lib/components
194
- [article]: http://ruby-lang.info/blog/you-underestimate-the-power-of-ioc-3fh
170
+ [rad_core_components]: https://github.com/alexeypetrushin/rad_core/tree/master/lib/components
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: micon
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.19
4
+ version: 0.1.20
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2011-08-15 00:00:00.000000000Z
12
+ date: 2011-08-16 00:00:00.000000000Z
13
13
  dependencies: []
14
14
  description:
15
15
  email:
@@ -70,5 +70,5 @@ rubyforge_project:
70
70
  rubygems_version: 1.8.6
71
71
  signing_key:
72
72
  specification_version: 3
73
- summary: Micon IoC assembles and manages Your Application
73
+ summary: Silent and invisible Killer of dependencies and configs
74
74
  test_files: []