alki 0.13.3 → 0.14.0
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 +5 -5
- data/.gitignore +2 -1
- data/.travis.yml +5 -0
- data/README.adoc +357 -75
- data/alki.gemspec +6 -5
- data/lib/alki.rb +14 -10
- data/lib/alki/assembly/types/service.rb +2 -2
- data/lib/alki/execution/tag_map.rb +1 -1
- data/lib/alki/version.rb +1 -1
- data/test/feature/auto_group_test.rb +1 -1
- data/test/feature/mounts_test.rb +1 -1
- data/test/feature/overrides_test.rb +1 -1
- data/test/feature/references_test.rb +2 -2
- data/test/feature/try_mounts_test.rb +2 -2
- data/test/feature/values_test.rb +1 -1
- metadata +29 -31
- data/bin/alki +0 -17
- data/bin/bundler +0 -17
- data/bin/rake +0 -17
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
|
-
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
2
|
+
SHA256:
|
|
3
|
+
metadata.gz: 0c6c996e3cc167d5050b102082788df3b5a903c04f7ac47c916a3e972d9b08b4
|
|
4
|
+
data.tar.gz: '0998b6b90e8662383ee9dbeb612eea8d46d9f8e7f71facb5dcb6eca9c445a66e'
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: ae2e60c2e81b564e29af9867fc4377200ee52a65cb5b14f4703b22e196a9e79fec6e45284e87aea3e876c457f66497aaf2bab4850d8900f3e2e69e12b6d185f5
|
|
7
|
+
data.tar.gz: 9d2d44039ded951d456e1a937f17c95499dca97e99dc968fdc5aedc5812e75ed022495efec372fba2ac6a165815e289563d0ec69693dec1fb2b9e1969b4c2ec8
|
data/.gitignore
CHANGED
data/.travis.yml
ADDED
data/README.adoc
CHANGED
|
@@ -1,21 +1,27 @@
|
|
|
1
|
-
|
|
1
|
+
= What is Alki?
|
|
2
|
+
|
|
3
|
+
image:https://travis-ci.org/alki-project/alki.svg?branch=master["Build Status", link="https://travis-ci.org/alki-project/alki"]
|
|
2
4
|
|
|
3
5
|
Alki (AL-kai) is a Dependency Injection framework for Ruby. Alki is designed to help organize and scale your project,
|
|
4
6
|
so you can focus on the important stuff.
|
|
5
|
-
It can be used alongside frameworks such as Ruby on Rails.
|
|
7
|
+
It can be used alongside frameworks such as http://alki.io/projects/alki-rails.html[Ruby on Rails].
|
|
6
8
|
|
|
7
9
|
Some high level features:
|
|
8
10
|
|
|
9
11
|
* Easily manage objects and dependencies
|
|
10
12
|
* Enables writing reusable and testable code
|
|
11
13
|
* Requires no annotations, mixins, or other changes to your code.
|
|
12
|
-
*
|
|
13
|
-
* Automatic
|
|
14
|
-
* Powerful
|
|
14
|
+
* http://alki.io/projects/alki-console.html[Developer console] (built on pry)
|
|
15
|
+
* Automatic http://alki.io/projects/alki-reload.html[code reloading]
|
|
16
|
+
* Powerful http://alki.io/projects/alki-dsl/[DSL toolkit]
|
|
15
17
|
* Extensible
|
|
16
18
|
|
|
19
|
+
For more documentation, check out http://alki.io[alki.io].
|
|
20
|
+
|
|
21
|
+
For questions or discussion about Alki, head over to the https://groups.google.com/forum/#!forum/alki-project[Google Group].
|
|
17
22
|
|
|
18
|
-
|
|
23
|
+
[[installation]]
|
|
24
|
+
== Installation
|
|
19
25
|
|
|
20
26
|
Add this line to your application's Gemfile:
|
|
21
27
|
|
|
@@ -31,19 +37,298 @@ Or install it yourself as:
|
|
|
31
37
|
|
|
32
38
|
$ gem install alki
|
|
33
39
|
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
[NOTE]
|
|
37
|
-
Full "todo" example can be found https://github.com/alki-project/alki-examples/tree/master/todo[here]
|
|
40
|
+
== How to use Alki
|
|
38
41
|
|
|
39
42
|
Alki simplifies project organization by pulling out all of the "connective tissue"
|
|
40
|
-
that connects
|
|
41
|
-
|
|
43
|
+
that connects your classes and modules together.
|
|
44
|
+
Alki provides a central place to build your application objects,
|
|
45
|
+
where they can easily refer to other objects,
|
|
46
|
+
and access configuration settings.
|
|
47
|
+
|
|
48
|
+
For example,
|
|
49
|
+
if your project has an http client
|
|
50
|
+
|
|
51
|
+
.my_project/http_client.rb
|
|
52
|
+
```ruby
|
|
53
|
+
module MyProject
|
|
54
|
+
class HttpClient
|
|
55
|
+
...
|
|
56
|
+
end
|
|
57
|
+
end
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
you might normally use it by either creating a new instance of it when needed,
|
|
61
|
+
or directly calling methods on the class.
|
|
62
|
+
|
|
63
|
+
```ruby
|
|
64
|
+
client = MyProject::HttpClient.new
|
|
65
|
+
client.get '/page1.html'
|
|
66
|
+
# -or-
|
|
67
|
+
MyProject::HttpClient.get '/page1.html'
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
With Alki, you would instead define instructions for how to build the http client.
|
|
71
|
+
|
|
72
|
+
.config/assembly.rb
|
|
73
|
+
```ruby
|
|
74
|
+
Alki do
|
|
75
|
+
service :http_client do
|
|
76
|
+
require 'my_project/http_client'
|
|
77
|
+
MyProject::HttpClient.new
|
|
78
|
+
end
|
|
79
|
+
end
|
|
80
|
+
```
|
|
42
81
|
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
an Assembly
|
|
82
|
+
The 'service' method defines a new object with the name 'http_client',
|
|
83
|
+
and the provided block contains the code needed to build it.
|
|
84
|
+
|
|
85
|
+
To use the http client, an "Assembly" for the project has to be created.
|
|
86
|
+
Assemblies are container objects that hold your application objects once
|
|
87
|
+
they're built.
|
|
88
|
+
|
|
89
|
+
Typically you can just add the following code to your project's main library file.
|
|
90
|
+
More information can be found about this method http://alki.io/assemblies/project_assemblies.html[here].
|
|
91
|
+
|
|
92
|
+
.lib/my_project.rb
|
|
93
|
+
```ruby
|
|
94
|
+
require 'alki'
|
|
95
|
+
Alki.project_assembly!
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
This will add a 'new' method to the the MyProject module,
|
|
99
|
+
which will return a new Assembly instance.
|
|
100
|
+
The http client can be accessed by calling the method that matches the name we chose for it
|
|
101
|
+
when it was defined,
|
|
102
|
+
'http_client'.
|
|
103
|
+
|
|
104
|
+
```ruby
|
|
105
|
+
require 'my_project'
|
|
106
|
+
|
|
107
|
+
app = MyProject.new
|
|
108
|
+
app.http_client.get '/page1.html'
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
=== Configuration Settings
|
|
112
|
+
|
|
113
|
+
Most projects, at some point,
|
|
114
|
+
have to deal with configuration settings.
|
|
115
|
+
|
|
116
|
+
In Ruby the typical pattern is to reference Modules and Classes directly,
|
|
117
|
+
either by constructing them on demand when needed,
|
|
118
|
+
or calling class methods on them.
|
|
119
|
+
|
|
120
|
+
Often this leaves Modules and Classes to essentially have to configure themselves.
|
|
121
|
+
Sometimes this is by pulling configuration from the environment or a configration file,
|
|
122
|
+
sometimes it's by requiring a global variable to be set before the class is used.
|
|
123
|
+
|
|
124
|
+
This means that classes are often cluttered with configuration code.
|
|
125
|
+
Classes from different libraries might have different, inconsistent ways of being configured,
|
|
126
|
+
and it can be difficult if not impossible to change how they're configured.
|
|
127
|
+
|
|
128
|
+
In Alki, configuration becomes straightforward.
|
|
129
|
+
Classes can just take configuration settings as initializer parameters,
|
|
130
|
+
without worrying about where they comes from.
|
|
131
|
+
|
|
132
|
+
.lib/my_project/http_client.rb
|
|
133
|
+
```
|
|
134
|
+
module MyProject
|
|
135
|
+
class HttpClient
|
|
136
|
+
def initializer(base_uri)
|
|
137
|
+
@base_uri = base_uri
|
|
138
|
+
end
|
|
139
|
+
...
|
|
140
|
+
end
|
|
141
|
+
end
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
Then the Assembly can be updated to pass in a configuration parameter.
|
|
145
|
+
We can also define a new element for our base_url setting.
|
|
146
|
+
|
|
147
|
+
.config/assembly.rb
|
|
148
|
+
```ruby
|
|
149
|
+
Alki do
|
|
150
|
+
set :http_base_url do
|
|
151
|
+
ENV.fetch('HTTP_BASE_URL')
|
|
152
|
+
end
|
|
153
|
+
|
|
154
|
+
service :http_client do
|
|
155
|
+
require 'my_project/http_client'
|
|
156
|
+
MyProject::HttpClient.new http_base_url
|
|
157
|
+
end
|
|
158
|
+
end
|
|
159
|
+
```
|
|
160
|
+
|
|
161
|
+
The 'set' method is used to define simple values in the Assembly,
|
|
162
|
+
and the http client can refer to it by name.
|
|
163
|
+
|
|
164
|
+
Nothing changes with how we use the http client,
|
|
165
|
+
but it's now pulling it's configuration from the environment.
|
|
166
|
+
|
|
167
|
+
Changing this to have a default value,
|
|
168
|
+
pull from a different source,
|
|
169
|
+
or have multiple clients with different configuration parameters
|
|
170
|
+
can be done easily without changing the class code.
|
|
171
|
+
|
|
172
|
+
For example,
|
|
173
|
+
to change the settings to come from a YAML file we can define a new
|
|
174
|
+
element to parse the YAML file,
|
|
175
|
+
and then redifine our setting to pull it's value from the parsed options.
|
|
176
|
+
Note that the order doesn't matter.
|
|
177
|
+
Even if a dependency is defined after an element that uses it,
|
|
178
|
+
the objects will still be built in the correct order.
|
|
179
|
+
|
|
180
|
+
.config/assembly.rb
|
|
181
|
+
```ruby
|
|
182
|
+
Alki do
|
|
183
|
+
set :yaml_settings do
|
|
184
|
+
require 'yaml'
|
|
185
|
+
YAML.load_file File.join(config_dir,'settings.yml')
|
|
186
|
+
end
|
|
187
|
+
|
|
188
|
+
set :http_base_url do
|
|
189
|
+
yaml_settings['http_base_ur']
|
|
190
|
+
end
|
|
191
|
+
|
|
192
|
+
service :http_client do
|
|
193
|
+
require 'my_project/http_client'
|
|
194
|
+
MyProject::HttpClient.new http_base_url
|
|
195
|
+
end
|
|
196
|
+
end
|
|
197
|
+
```
|
|
198
|
+
|
|
199
|
+
No changes to the class,
|
|
200
|
+
or in this case even the build code for the http client,
|
|
201
|
+
are required.
|
|
202
|
+
|
|
203
|
+
Configuration settings can be grouped together in the assembly,
|
|
204
|
+
to namespace them.
|
|
205
|
+
This group can be called anything, but we'll call it 'settings'.
|
|
206
|
+
|
|
207
|
+
.config/assembly.rb
|
|
208
|
+
```ruby
|
|
209
|
+
Alki do
|
|
210
|
+
group :settings do
|
|
211
|
+
set :http_base_url do
|
|
212
|
+
yaml_settings['http_base_ur']
|
|
213
|
+
end
|
|
214
|
+
|
|
215
|
+
set :yaml_settings do
|
|
216
|
+
require 'yaml'
|
|
217
|
+
YAML.parse(File.read(File.join(config_dir,'settings.yml')))
|
|
218
|
+
end
|
|
219
|
+
end
|
|
220
|
+
|
|
221
|
+
service :http_client do
|
|
222
|
+
require 'my_project/http_client'
|
|
223
|
+
MyProject::HttpClient.new settings.http_base_url
|
|
224
|
+
end
|
|
225
|
+
end
|
|
226
|
+
```
|
|
227
|
+
|
|
228
|
+
The can also be moved to an entirely different file to keep them
|
|
229
|
+
seperate from your application objects.
|
|
230
|
+
|
|
231
|
+
.config/settings.rb
|
|
232
|
+
```ruby
|
|
233
|
+
Alki do
|
|
234
|
+
set :http_base_url do
|
|
235
|
+
yaml_settings['http_base_ur']
|
|
236
|
+
end
|
|
237
|
+
|
|
238
|
+
set :yaml_settings do
|
|
239
|
+
require 'yaml'
|
|
240
|
+
YAML.parse(File.read(File.join(config_dir,'settings.yml')))
|
|
241
|
+
end
|
|
242
|
+
end
|
|
243
|
+
```
|
|
244
|
+
|
|
245
|
+
.config/assembly.rb
|
|
246
|
+
```ruby
|
|
247
|
+
Alki do
|
|
248
|
+
load :settings
|
|
249
|
+
|
|
250
|
+
service :http_client do
|
|
251
|
+
require 'my_project/http_client'
|
|
252
|
+
MyProject::HttpClient.new settings.http_base_url
|
|
253
|
+
end
|
|
254
|
+
end
|
|
255
|
+
```
|
|
256
|
+
|
|
257
|
+
== Dependency Injection
|
|
258
|
+
|
|
259
|
+
Dependency Injection is a way of designing your classes to maximise
|
|
260
|
+
their modularity and reusability.
|
|
261
|
+
|
|
262
|
+
Much like with configuration settings,
|
|
263
|
+
instead of directly referencing a classes dependencies a depenency injected
|
|
264
|
+
class takes it's dependencies as arguments.
|
|
265
|
+
|
|
266
|
+
The advantage of this is that classes can be developed and tested in isolation,
|
|
267
|
+
can have dependencies easily changed by other code (like users of a library),
|
|
268
|
+
or have multiple instances with different dependencies.
|
|
269
|
+
|
|
270
|
+
Like configuration settings,
|
|
271
|
+
a lot of Ruby projects end up needing some amount of dependency injection,
|
|
272
|
+
but it's typically implemented in an ad-hoc way with class variables or other global
|
|
273
|
+
variables.
|
|
274
|
+
|
|
275
|
+
With Alki, dependency injection is the norm and very straightforward.
|
|
276
|
+
|
|
277
|
+
Perhaps we have client for API that works over HTTP.
|
|
278
|
+
We can write our API client so that it takes an HTTP client as an arugment
|
|
279
|
+
and just calls methods on it.
|
|
280
|
+
It doesn't need to pick a particular client library or decide what configuration
|
|
281
|
+
settings it should have.
|
|
282
|
+
|
|
283
|
+
.lib/my_project/api_client.rb
|
|
284
|
+
```ruby
|
|
285
|
+
module MyProject
|
|
286
|
+
class ApiClient
|
|
287
|
+
def initialize(http_client)
|
|
288
|
+
@http_client = http_client
|
|
289
|
+
end
|
|
290
|
+
|
|
291
|
+
def all
|
|
292
|
+
parse_response @http_client.get('/all.json')
|
|
293
|
+
end
|
|
294
|
+
|
|
295
|
+
...
|
|
296
|
+
end
|
|
297
|
+
end
|
|
298
|
+
```
|
|
299
|
+
|
|
300
|
+
With this design it's easy to change out the http client,
|
|
301
|
+
or provide a stubbed or mocked one for testing.
|
|
302
|
+
It maximizes the reusability of our API client
|
|
303
|
+
because it only handles one thing
|
|
304
|
+
(Single Responsibility Principle).
|
|
305
|
+
|
|
306
|
+
To add it to the previous assembly definition.
|
|
307
|
+
|
|
308
|
+
.config/assembly.rb
|
|
309
|
+
```ruby
|
|
310
|
+
load :settings
|
|
311
|
+
|
|
312
|
+
service :api_client do
|
|
313
|
+
require 'my_project/api_client'
|
|
314
|
+
MyProject::ApiClient.new http_client
|
|
315
|
+
end
|
|
316
|
+
|
|
317
|
+
service :http_client do
|
|
318
|
+
require 'my_project/http_client'
|
|
319
|
+
MyProject::HttpClient.new settings.http_base_url
|
|
320
|
+
end
|
|
321
|
+
```
|
|
322
|
+
|
|
323
|
+
== Example
|
|
324
|
+
|
|
325
|
+
[NOTE]
|
|
326
|
+
Full "todo" source code can be found https://github.com/alki-project/alki-examples/tree/master/todo[here]
|
|
327
|
+
|
|
328
|
+
To demonstrate how a full Alki project can be put together,
|
|
329
|
+
we'll go through an example application.
|
|
330
|
+
This application is a little todo list command line utility
|
|
331
|
+
that stores the todo list in a json file.
|
|
47
332
|
|
|
48
333
|
.lib/todo.rb
|
|
49
334
|
```ruby
|
|
@@ -61,25 +346,25 @@ $ bundle exec irb -Ilib
|
|
|
61
346
|
=> #<Todo:21964520>
|
|
62
347
|
```
|
|
63
348
|
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
Adding things to the assembly requires an assembly definition file. By convention this is
|
|
67
|
-
named `config/assembly.rb` and is built using a simple DSL. There are
|
|
68
|
-
a handful of different element types in Assemblies. Below are a few of the
|
|
69
|
-
most common. Full documentation of the DSL can be found at http://alki.io[alki.io].
|
|
349
|
+
[[defining-elements]]
|
|
350
|
+
=== Defining Elements
|
|
70
351
|
|
|
352
|
+
Adding things to the assembly requires an Assembly definition file.
|
|
353
|
+
By convention this is named `config/assembly.rb` and is built using a DSL.
|
|
354
|
+
There are a handful of different element types in Assemblies.
|
|
71
355
|
Elements can refer to other elements, and can be defined in any order.
|
|
72
356
|
|
|
357
|
+
Full documentation of the DSL can be found http://alki.io/dsl/[here].
|
|
358
|
+
|
|
359
|
+
Below is an example Assembly definition for the todo application
|
|
360
|
+
which uses a few of the core element types.
|
|
361
|
+
|
|
73
362
|
.config/assembly.rb
|
|
74
363
|
```ruby
|
|
75
364
|
Alki do
|
|
76
|
-
|
|
77
|
-
set(:home) { ENV['HOME'] } <2>
|
|
78
|
-
set(:db_path) { ENV['TODO_DB_PATH'] || File.join(home,'.todo_db') }
|
|
79
|
-
set :prompt, 'todo> '
|
|
80
|
-
end
|
|
365
|
+
load :settings
|
|
81
366
|
|
|
82
|
-
service :interface do
|
|
367
|
+
service :interface do
|
|
83
368
|
require 'todo/readline_interface'
|
|
84
369
|
Todo::ReadlineInterface.new settings.prompt, handler
|
|
85
370
|
end
|
|
@@ -100,11 +385,21 @@ Alki do
|
|
|
100
385
|
end
|
|
101
386
|
end
|
|
102
387
|
```
|
|
103
|
-
<1> `group` allows bundling together subelements (and which can be moved to their own files)
|
|
104
|
-
<2> `set` defines simple values
|
|
105
|
-
<3> `service` defines our main application objects
|
|
106
388
|
|
|
107
|
-
|
|
389
|
+
Along with a settings file to define our application settings.
|
|
390
|
+
|
|
391
|
+
.config/settings.rb
|
|
392
|
+
```ruby
|
|
393
|
+
Alki do
|
|
394
|
+
set(:home) { ENV['HOME'] }
|
|
395
|
+
set(:db_path) { ENV['TODO_DB_PATH'] || File.join(home,'.todo_db') }
|
|
396
|
+
set :prompt, 'todo> '
|
|
397
|
+
end
|
|
398
|
+
```
|
|
399
|
+
|
|
400
|
+
Settings and services can be accessed by requiring the main "lib/todo.rb" file,
|
|
401
|
+
creating a new assembly instance,
|
|
402
|
+
and then calling methods to refer to the different elements.
|
|
108
403
|
|
|
109
404
|
```
|
|
110
405
|
$ bundle exec irb -Ilib
|
|
@@ -112,7 +407,9 @@ $ bundle exec irb -Ilib
|
|
|
112
407
|
=> true
|
|
113
408
|
2.4.0 :002 > todo = Todo.new
|
|
114
409
|
=> #<Todo:21964520>
|
|
115
|
-
2.4.0 :003 > todo.
|
|
410
|
+
2.4.0 :003 > todo.settings.prompt
|
|
411
|
+
=> "> "
|
|
412
|
+
2.4.0 :004 > todo.interface.run
|
|
116
413
|
> ?
|
|
117
414
|
All commands can be shortened to their first letters
|
|
118
415
|
print
|
|
@@ -126,8 +423,11 @@ quit
|
|
|
126
423
|
|
|
127
424
|
```
|
|
128
425
|
|
|
129
|
-
The
|
|
130
|
-
|
|
426
|
+
The http://alki.io/projects/alki-console.html[alki-console] developer console gem can also be used to quickly work with assemblies.
|
|
427
|
+
It can be used by adding `gem 'alki-console'` to the Gemfile and running `bundle --binstubs` to add the console script to the 'bin' directory.
|
|
428
|
+
|
|
429
|
+
Elements can be accessed directly without having to manually create an
|
|
430
|
+
assembly instance.
|
|
131
431
|
|
|
132
432
|
```
|
|
133
433
|
$ bin/alki-console
|
|
@@ -135,63 +435,45 @@ todo> settings.prompt
|
|
|
135
435
|
=> 'todo> '
|
|
136
436
|
```
|
|
137
437
|
|
|
438
|
+
[[executable]]
|
|
138
439
|
### Creating an executable
|
|
139
440
|
|
|
140
|
-
Read more about creating executables with Alki
|
|
141
|
-
|
|
441
|
+
Read more about creating executables with Alki,
|
|
442
|
+
including how to create executables to distribute in a gem,
|
|
443
|
+
http://alki.io/assemblies/executables.html[here]
|
|
142
444
|
|
|
143
445
|
In the todo example, it's a CLI utility so it requires an executable.
|
|
144
446
|
The executable just needs to require the main project file,
|
|
145
447
|
create a new instance of the assembly,
|
|
146
448
|
and call a method on a service.
|
|
147
449
|
|
|
148
|
-
.
|
|
450
|
+
.bin/todo
|
|
149
451
|
```ruby
|
|
452
|
+
#!/usr/bin/env ruby
|
|
453
|
+
|
|
454
|
+
# Setup
|
|
455
|
+
require 'bundler/setup'
|
|
456
|
+
require 'alki/bin'
|
|
457
|
+
|
|
150
458
|
require 'todo'
|
|
151
459
|
Todo.new.interface.run
|
|
152
460
|
```
|
|
153
461
|
|
|
154
|
-
### Splitting up the Assembly configuration
|
|
155
|
-
|
|
156
|
-
As a project grows, it's helpful to be able to split out
|
|
157
|
-
parts of the Assembly configuration into multiple files.
|
|
158
|
-
|
|
159
|
-
This can be accomplished with the `load` method in the DSL,
|
|
160
|
-
which will load the named file and add it the elements
|
|
161
|
-
defined in it as a group in the assembly.
|
|
162
|
-
|
|
163
|
-
For example, it's common to split out application settings into
|
|
164
|
-
a separate config file.
|
|
165
|
-
|
|
166
|
-
.config/settings.rb
|
|
167
|
-
```ruby
|
|
168
|
-
Alki do
|
|
169
|
-
set(:home) { ENV['HOME'] }
|
|
170
|
-
set(:db_path) { ENV['TODO_DB_PATH'] || File.join(home,'.todo_db') }
|
|
171
|
-
set :prompt, 'todo> '
|
|
172
|
-
end
|
|
173
462
|
```
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
service :interface do
|
|
181
|
-
require 'todo/readline_interface'
|
|
182
|
-
Todo::ReadlineInterface.new settings.prompt, handler
|
|
183
|
-
end
|
|
184
|
-
|
|
185
|
-
...
|
|
186
|
-
end
|
|
463
|
+
$ bin/todo
|
|
464
|
+
> print
|
|
465
|
+
1. take out the trash
|
|
466
|
+
> quit
|
|
467
|
+
$
|
|
187
468
|
```
|
|
188
469
|
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
Further documentation can be found at http://alki.io[alki.io].
|
|
470
|
+
== Documentation
|
|
192
471
|
|
|
193
|
-
|
|
472
|
+
More documentation can be found at http://alki.io[alki.io],
|
|
473
|
+
with in-depth explanations of http://alki.io/assemblies/[Assemblies],
|
|
474
|
+
http://alki.io/dsl/[the Assembly DSL], and other
|
|
475
|
+
http://alki.io/projects/[projects] that are part of Alki.
|
|
194
476
|
|
|
195
|
-
|
|
477
|
+
== Authors
|
|
196
478
|
|
|
197
479
|
Written by Matt Edlefsen
|
data/alki.gemspec
CHANGED
|
@@ -8,18 +8,19 @@ Gem::Specification.new do |spec|
|
|
|
8
8
|
spec.version = Alki::VERSION
|
|
9
9
|
spec.authors = ["Matt Edlefsen"]
|
|
10
10
|
spec.email = ["matt.edlefsen@gmail.com"]
|
|
11
|
-
spec.summary = %q{
|
|
12
|
-
spec.description = %q{
|
|
13
|
-
spec.homepage = "
|
|
11
|
+
spec.summary = %q{Dependency Injection for Ruby}
|
|
12
|
+
spec.description = %q{Alki (AL-kai) is a Dependency Injection framework for Ruby. Helps organize and scale your project, so you can focus on the important stuff.}
|
|
13
|
+
spec.homepage = "http://alki.io"
|
|
14
14
|
spec.license = "MIT"
|
|
15
15
|
spec.files = `git ls-files -z`.split("\x0")
|
|
16
16
|
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
|
17
17
|
spec.bindir = 'exe'
|
|
18
18
|
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
|
19
19
|
spec.require_paths = ["lib"]
|
|
20
|
+
spec.required_ruby_version = '>= 2.1.0'
|
|
20
21
|
|
|
21
|
-
spec.add_dependency "alki-dsl", "~> 0.
|
|
22
|
-
spec.add_dependency "alki-support", "~> 0.7"
|
|
22
|
+
spec.add_dependency "alki-dsl", "~> 0.6"
|
|
23
|
+
spec.add_dependency "alki-support", "~> 0.7", ">= 0.7.1"
|
|
23
24
|
spec.add_dependency "concurrent-ruby", "~> 1.0"
|
|
24
25
|
spec.add_dependency "ice_nine", "~> 0.11"
|
|
25
26
|
end
|
data/lib/alki.rb
CHANGED
|
@@ -3,16 +3,20 @@ require 'alki/assembly/builder'
|
|
|
3
3
|
|
|
4
4
|
Alki::Assembly::Builder.build project_assembly: __FILE__, load_mode: :require
|
|
5
5
|
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
6
|
+
class << Alki
|
|
7
|
+
def project_assembly!(opts={},&blk)
|
|
8
|
+
opts[:project_assembly] ||= caller_locations(1,1)[0].absolute_path
|
|
9
|
+
opts[:load_mode] = :require
|
|
10
|
+
Alki::Assembly::Builder.build(opts,&blk)
|
|
11
|
+
end
|
|
11
12
|
|
|
12
|
-
def
|
|
13
|
-
|
|
14
|
-
end
|
|
13
|
+
def create_assembly(opts={},&blk)
|
|
14
|
+
Alki::Assembly::Builder.build(opts,&blk)
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def new(opts={},&blk)
|
|
18
|
+
Alki.create_assembly(opts,&blk).new
|
|
19
|
+
end
|
|
15
20
|
|
|
16
|
-
|
|
17
|
-
Alki.create_assembly(opts,&blk).new
|
|
21
|
+
alias_method :singleton_assembly, :new
|
|
18
22
|
end
|
|
@@ -4,10 +4,10 @@ Alki do
|
|
|
4
4
|
attr :block
|
|
5
5
|
|
|
6
6
|
output do
|
|
7
|
-
all_overlays = data[:overlays]
|
|
7
|
+
all_overlays = (data[:overlays] && data[:overlays].overlays) || []
|
|
8
8
|
value_overlays = all_overlays[:value] || []
|
|
9
9
|
reference_overlays = all_overlays[:reference] || []
|
|
10
|
-
tags = data[:tags]
|
|
10
|
+
tags = (data[:tags] && data[:tags].tags) || {}
|
|
11
11
|
methods = {
|
|
12
12
|
__build__: block,
|
|
13
13
|
__apply_overlays__: -> obj, overlays {
|
data/lib/alki/version.rb
CHANGED
|
@@ -13,7 +13,7 @@ describe 'Auto Group' do
|
|
|
13
13
|
end
|
|
14
14
|
|
|
15
15
|
it 'should create a group containing all items' do
|
|
16
|
-
@obj.grp.children.must_equal [:a,:one]
|
|
16
|
+
@obj.grp.children.sort.must_equal [:a,:one]
|
|
17
17
|
@obj.grp.one.value.must_equal 1
|
|
18
18
|
@obj.grp.a.children.must_equal [:two]
|
|
19
19
|
@obj.grp.a.two.value.must_equal 2
|
data/test/feature/mounts_test.rb
CHANGED
|
@@ -3,7 +3,7 @@ require 'alki/feature_test'
|
|
|
3
3
|
describe 'References' do
|
|
4
4
|
describe 'circular references' do
|
|
5
5
|
before do
|
|
6
|
-
@assembly = Alki.
|
|
6
|
+
@assembly = Alki.new do
|
|
7
7
|
set :a do
|
|
8
8
|
b
|
|
9
9
|
end
|
|
@@ -35,7 +35,7 @@ describe 'References' do
|
|
|
35
35
|
|
|
36
36
|
describe 'reference objects' do
|
|
37
37
|
before do
|
|
38
|
-
@obj = Alki.
|
|
38
|
+
@obj = Alki.new do
|
|
39
39
|
service :broken do
|
|
40
40
|
1.foo
|
|
41
41
|
end
|
|
@@ -2,7 +2,7 @@ require 'alki/feature_test'
|
|
|
2
2
|
|
|
3
3
|
describe 'Try mounts' do
|
|
4
4
|
it 'should not mount if other assembly can be found' do
|
|
5
|
-
obj = Alki.
|
|
5
|
+
obj = Alki.new do
|
|
6
6
|
try_mount :other, 'missing_assembly'
|
|
7
7
|
set :val do
|
|
8
8
|
respond_to? :other
|
|
@@ -12,7 +12,7 @@ describe 'Try mounts' do
|
|
|
12
12
|
end
|
|
13
13
|
|
|
14
14
|
it 'should mount if other assembly can be found' do
|
|
15
|
-
obj = Alki.
|
|
15
|
+
obj = Alki.new do
|
|
16
16
|
try_mount :other, 'example' # example fixture assembly
|
|
17
17
|
set :val do
|
|
18
18
|
respond_to? :other
|
data/test/feature/values_test.rb
CHANGED
metadata
CHANGED
|
@@ -1,79 +1,79 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: alki
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.14.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Matt Edlefsen
|
|
8
|
-
autorequire:
|
|
8
|
+
autorequire:
|
|
9
9
|
bindir: exe
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2018-
|
|
11
|
+
date: 2018-04-01 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
|
-
name: alki-dsl
|
|
15
14
|
requirement: !ruby/object:Gem::Requirement
|
|
16
15
|
requirements:
|
|
17
16
|
- - "~>"
|
|
18
17
|
- !ruby/object:Gem::Version
|
|
19
|
-
version: '0.
|
|
20
|
-
|
|
21
|
-
- !ruby/object:Gem::Version
|
|
22
|
-
version: 0.5.1
|
|
23
|
-
type: :runtime
|
|
18
|
+
version: '0.6'
|
|
19
|
+
name: alki-dsl
|
|
24
20
|
prerelease: false
|
|
21
|
+
type: :runtime
|
|
25
22
|
version_requirements: !ruby/object:Gem::Requirement
|
|
26
23
|
requirements:
|
|
27
24
|
- - "~>"
|
|
28
25
|
- !ruby/object:Gem::Version
|
|
29
|
-
version: '0.
|
|
30
|
-
- - ">="
|
|
31
|
-
- !ruby/object:Gem::Version
|
|
32
|
-
version: 0.5.1
|
|
26
|
+
version: '0.6'
|
|
33
27
|
- !ruby/object:Gem::Dependency
|
|
34
|
-
name: alki-support
|
|
35
28
|
requirement: !ruby/object:Gem::Requirement
|
|
36
29
|
requirements:
|
|
37
30
|
- - "~>"
|
|
38
31
|
- !ruby/object:Gem::Version
|
|
39
32
|
version: '0.7'
|
|
40
|
-
|
|
33
|
+
- - ">="
|
|
34
|
+
- !ruby/object:Gem::Version
|
|
35
|
+
version: 0.7.1
|
|
36
|
+
name: alki-support
|
|
41
37
|
prerelease: false
|
|
38
|
+
type: :runtime
|
|
42
39
|
version_requirements: !ruby/object:Gem::Requirement
|
|
43
40
|
requirements:
|
|
44
41
|
- - "~>"
|
|
45
42
|
- !ruby/object:Gem::Version
|
|
46
43
|
version: '0.7'
|
|
44
|
+
- - ">="
|
|
45
|
+
- !ruby/object:Gem::Version
|
|
46
|
+
version: 0.7.1
|
|
47
47
|
- !ruby/object:Gem::Dependency
|
|
48
|
-
name: concurrent-ruby
|
|
49
48
|
requirement: !ruby/object:Gem::Requirement
|
|
50
49
|
requirements:
|
|
51
50
|
- - "~>"
|
|
52
51
|
- !ruby/object:Gem::Version
|
|
53
52
|
version: '1.0'
|
|
54
|
-
|
|
53
|
+
name: concurrent-ruby
|
|
55
54
|
prerelease: false
|
|
55
|
+
type: :runtime
|
|
56
56
|
version_requirements: !ruby/object:Gem::Requirement
|
|
57
57
|
requirements:
|
|
58
58
|
- - "~>"
|
|
59
59
|
- !ruby/object:Gem::Version
|
|
60
60
|
version: '1.0'
|
|
61
61
|
- !ruby/object:Gem::Dependency
|
|
62
|
-
name: ice_nine
|
|
63
62
|
requirement: !ruby/object:Gem::Requirement
|
|
64
63
|
requirements:
|
|
65
64
|
- - "~>"
|
|
66
65
|
- !ruby/object:Gem::Version
|
|
67
66
|
version: '0.11'
|
|
68
|
-
|
|
67
|
+
name: ice_nine
|
|
69
68
|
prerelease: false
|
|
69
|
+
type: :runtime
|
|
70
70
|
version_requirements: !ruby/object:Gem::Requirement
|
|
71
71
|
requirements:
|
|
72
72
|
- - "~>"
|
|
73
73
|
- !ruby/object:Gem::Version
|
|
74
74
|
version: '0.11'
|
|
75
|
-
description:
|
|
76
|
-
and
|
|
75
|
+
description: Alki (AL-kai) is a Dependency Injection framework for Ruby. Helps organize
|
|
76
|
+
and scale your project, so you can focus on the important stuff.
|
|
77
77
|
email:
|
|
78
78
|
- matt.edlefsen@gmail.com
|
|
79
79
|
executables: []
|
|
@@ -81,14 +81,12 @@ extensions: []
|
|
|
81
81
|
extra_rdoc_files: []
|
|
82
82
|
files:
|
|
83
83
|
- ".gitignore"
|
|
84
|
+
- ".travis.yml"
|
|
84
85
|
- Gemfile
|
|
85
86
|
- LICENSE.txt
|
|
86
87
|
- README.adoc
|
|
87
88
|
- Rakefile
|
|
88
89
|
- alki.gemspec
|
|
89
|
-
- bin/alki
|
|
90
|
-
- bin/bundler
|
|
91
|
-
- bin/rake
|
|
92
90
|
- config/assembly.rb
|
|
93
91
|
- lib/alki.rb
|
|
94
92
|
- lib/alki/assembly.rb
|
|
@@ -171,11 +169,11 @@ files:
|
|
|
171
169
|
- test/integration/dsls/assembly_test.rb
|
|
172
170
|
- test/integration/dsls/assembly_type_test.rb
|
|
173
171
|
- test/integration/dsls/service_dsl_test.rb
|
|
174
|
-
homepage:
|
|
172
|
+
homepage: http://alki.io
|
|
175
173
|
licenses:
|
|
176
174
|
- MIT
|
|
177
175
|
metadata: {}
|
|
178
|
-
post_install_message:
|
|
176
|
+
post_install_message:
|
|
179
177
|
rdoc_options: []
|
|
180
178
|
require_paths:
|
|
181
179
|
- lib
|
|
@@ -183,18 +181,18 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
|
183
181
|
requirements:
|
|
184
182
|
- - ">="
|
|
185
183
|
- !ruby/object:Gem::Version
|
|
186
|
-
version:
|
|
184
|
+
version: 2.1.0
|
|
187
185
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
188
186
|
requirements:
|
|
189
187
|
- - ">="
|
|
190
188
|
- !ruby/object:Gem::Version
|
|
191
189
|
version: '0'
|
|
192
190
|
requirements: []
|
|
193
|
-
rubyforge_project:
|
|
194
|
-
rubygems_version: 2.6.
|
|
195
|
-
signing_key:
|
|
191
|
+
rubyforge_project:
|
|
192
|
+
rubygems_version: 2.6.13
|
|
193
|
+
signing_key:
|
|
196
194
|
specification_version: 4
|
|
197
|
-
summary:
|
|
195
|
+
summary: Dependency Injection for Ruby
|
|
198
196
|
test_files:
|
|
199
197
|
- test/feature/alki_test.rb
|
|
200
198
|
- test/feature/auto_group_test.rb
|
data/bin/alki
DELETED
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env ruby
|
|
2
|
-
# frozen_string_literal: true
|
|
3
|
-
#
|
|
4
|
-
# This file was generated by Bundler.
|
|
5
|
-
#
|
|
6
|
-
# The application 'alki' is installed as part of a gem, and
|
|
7
|
-
# this file is here to facilitate running it.
|
|
8
|
-
#
|
|
9
|
-
|
|
10
|
-
require "pathname"
|
|
11
|
-
ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../../Gemfile",
|
|
12
|
-
Pathname.new(__FILE__).realpath)
|
|
13
|
-
|
|
14
|
-
require "rubygems"
|
|
15
|
-
require "bundler/setup"
|
|
16
|
-
|
|
17
|
-
load Gem.bin_path("alki", "alki")
|
data/bin/bundler
DELETED
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env ruby
|
|
2
|
-
# frozen_string_literal: true
|
|
3
|
-
#
|
|
4
|
-
# This file was generated by Bundler.
|
|
5
|
-
#
|
|
6
|
-
# The application 'bundler' is installed as part of a gem, and
|
|
7
|
-
# this file is here to facilitate running it.
|
|
8
|
-
#
|
|
9
|
-
|
|
10
|
-
require "pathname"
|
|
11
|
-
ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../../Gemfile",
|
|
12
|
-
Pathname.new(__FILE__).realpath)
|
|
13
|
-
|
|
14
|
-
require "rubygems"
|
|
15
|
-
require "bundler/setup"
|
|
16
|
-
|
|
17
|
-
load Gem.bin_path("bundler", "bundler")
|
data/bin/rake
DELETED
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env ruby
|
|
2
|
-
# frozen_string_literal: true
|
|
3
|
-
#
|
|
4
|
-
# This file was generated by Bundler.
|
|
5
|
-
#
|
|
6
|
-
# The application 'rake' is installed as part of a gem, and
|
|
7
|
-
# this file is here to facilitate running it.
|
|
8
|
-
#
|
|
9
|
-
|
|
10
|
-
require "pathname"
|
|
11
|
-
ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../../Gemfile",
|
|
12
|
-
Pathname.new(__FILE__).realpath)
|
|
13
|
-
|
|
14
|
-
require "rubygems"
|
|
15
|
-
require "bundler/setup"
|
|
16
|
-
|
|
17
|
-
load Gem.bin_path("rake", "rake")
|