micon 0.1.19 → 0.1.20

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