alki 0.7.0 → 0.8.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 +4 -4
- data/{README.ad → README.adoc} +2 -2
- data/doc/{assemblies.ad → assemblies.adoc} +24 -9
- data/doc/{assembly_dsl.ad → assembly_dsl.adoc} +113 -12
- data/doc/{index.ad → index.adoc} +4 -3
- data/doc/{projects.ad → projects.adoc} +1 -0
- data/lib/alki/dsls/assembly_types/assembly.rb +1 -1
- data/lib/alki/feature_test.rb +7 -0
- data/lib/alki/test.rb +4 -5
- data/lib/alki/version.rb +1 -1
- metadata +8 -7
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 91b0f6c880177b0e4be1c5228c92b0295db5742a
|
4
|
+
data.tar.gz: 6c781108545400031137040024b040c3a67d9b16
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: cc46916b429be7d64b76b2e9e93d086493699d8303607d248471a55fed9da1ab13e7c01bc7b2b700a44c71180943c53fb766b72d50b3dd10dd75ec700e6816cc
|
7
|
+
data.tar.gz: e17b68e68390ea600d2d5f2dabe48029696537d2d8ded480eec57cb1a6bf6601dc4035aaf666311ab63f3a28684dac9f571b2e8746e11885b204cfd5c2ccbe09
|
data/{README.ad → README.adoc}
RENAMED
@@ -4,9 +4,9 @@ Alki is a framework for creating projects that are modular, testable, and well o
|
|
4
4
|
|
5
5
|
It's goal is to remove uncertainty and friction when building Ruby projects, allowing developers to focus on implementing business logic.
|
6
6
|
|
7
|
-
# Synopsis
|
8
|
-
|
9
7
|
Best place to start would be to check out some examples:
|
10
8
|
|
11
9
|
* https://github.com/alki-project/alki-example
|
12
10
|
* https://github.com/alki-project/alki/tree/master/test/fixtures/example
|
11
|
+
|
12
|
+
Docs can be found at https://github.com/alki-project/alki/blob/master/doc/index.adoc
|
@@ -1,14 +1,25 @@
|
|
1
1
|
Assemblies
|
2
2
|
==========
|
3
|
+
:toc:
|
4
|
+
|
5
|
+
If a set of classes are your raw materials, an Assembly is the finished product,
|
6
|
+
ready to be used.
|
7
|
+
|
8
|
+
To get there, you provide Alki with your assembly definition, which acts as the instructions for
|
9
|
+
how to piece together your classes and objects. Assemblies are made up of elements, which are groups
|
10
|
+
of other elements, or various value types like services and factories.
|
11
|
+
|
12
|
+
Assembly definitions are written in a simple DSL.
|
3
13
|
|
4
14
|
Project Assemblies
|
5
15
|
------------------
|
6
16
|
|
7
|
-
Most of the time, a project will have a single assembly
|
17
|
+
Most of the time, a project will have a single assembly, so Alki makes having a single project wide
|
18
|
+
assembly especially easy.
|
8
19
|
|
9
20
|
First. in your project's `lib` directory create a ruby file for your assembly. If your assembly is
|
10
|
-
to be called `MyAssembly`, create `lib/my_assembly.rb`. If it's namespaced
|
11
|
-
as usual
|
21
|
+
to be called `MyAssembly`, create `lib/my_assembly.rb`. If it's namespaced put it in a subdirectory
|
22
|
+
as usual (i.e. `MyModule::MyAssembly` would go in `lib/my_module/my_assembly.rb`).
|
12
23
|
|
13
24
|
Your assembly file just needs two lines:
|
14
25
|
|
@@ -20,7 +31,8 @@ Alki.project_assembly!
|
|
20
31
|
It will detect the project root and what class name it should create automatically.
|
21
32
|
|
22
33
|
Second, a `config` directory must be created in the project root, and in that directory an `assembly.rb`
|
23
|
-
file should be created. It should
|
34
|
+
file should be created. It should contain an `Alki do ... end` block which contains the top level
|
35
|
+
definition for your Assembly.
|
24
36
|
|
25
37
|
```ruby
|
26
38
|
Alki do
|
@@ -47,6 +59,7 @@ It should be called with a block that contains the assembly DSL. It will return
|
|
47
59
|
be used directly or assigned to a constant.
|
48
60
|
|
49
61
|
```ruby
|
62
|
+
require 'alki'
|
50
63
|
assembly = Alki.create_assembly do
|
51
64
|
set :msg, "hello world"
|
52
65
|
func :run do
|
@@ -80,7 +93,7 @@ assembly = Alki.create_assembly do
|
|
80
93
|
end
|
81
94
|
```
|
82
95
|
|
83
|
-
|
96
|
+
One can use the logger service like so:
|
84
97
|
|
85
98
|
```ruby
|
86
99
|
instance = assembly.new
|
@@ -91,12 +104,12 @@ instance.util.logger.info "test"
|
|
91
104
|
|
92
105
|
### Overrides
|
93
106
|
|
94
|
-
Assembly overrides provide a way to
|
107
|
+
Assembly overrides provide a way to configure or customize an Assembly when
|
95
108
|
constructing an instance.
|
96
109
|
|
97
110
|
For example, using the assembly created above, one might want to change the IO object logged to.
|
98
111
|
|
99
|
-
The simplist way to do this is to provide a hash
|
112
|
+
The simplist way to do this is to provide a hash which will override values in the assembly (as if the `set`
|
100
113
|
command was called in the DSL):
|
101
114
|
|
102
115
|
```ruby
|
@@ -113,6 +126,7 @@ The limitiation of this is that it can only override basic values. To override m
|
|
113
126
|
a block can be given to `new` allowing the full assembly DSL.
|
114
127
|
|
115
128
|
```ruby
|
129
|
+
require 'alki'
|
116
130
|
class MyLogger
|
117
131
|
def initialize(io)
|
118
132
|
@io = io
|
@@ -134,5 +148,6 @@ instance.util.logger.info "test"
|
|
134
148
|
# output: INFO test
|
135
149
|
```
|
136
150
|
|
137
|
-
One thing of note is that elements from the assembly are
|
138
|
-
This can also be used to access the original versions of elements that have
|
151
|
+
One thing of note is that elements from the assembly are accessible in overrides via the `original`
|
152
|
+
method, as seen above. This can also be used to access the original versions of elements that have
|
153
|
+
been overriden.
|
@@ -1,10 +1,11 @@
|
|
1
1
|
Assembly DSL
|
2
|
-
|
2
|
+
============
|
3
|
+
:toc:
|
3
4
|
|
4
5
|
Building Assemblies is done via a DSL that makes putting together the pieces of your project easy.
|
5
6
|
|
6
|
-
Groups
|
7
|
-
|
7
|
+
Groups (group)
|
8
|
+
--------------
|
8
9
|
|
9
10
|
Groups are the basic way of organizing the elements of your Assembly. Creating elements at the top
|
10
11
|
level of an Assembly will place them in a root group, but subgroups are easily created via the `group`
|
@@ -18,30 +19,43 @@ assembly = Alki.create_assembly do
|
|
18
19
|
end
|
19
20
|
end
|
20
21
|
puts assembly.new.sub_group.val
|
22
|
+
|
23
|
+
#output: hello world
|
21
24
|
```
|
22
25
|
|
23
|
-
Scoping is also done by group, so that an element will be found by
|
26
|
+
Scoping is also done by group, so that an element will be found by searching through parent groups until
|
24
27
|
it is found.
|
25
28
|
|
26
29
|
```ruby
|
27
30
|
require 'alki'
|
28
31
|
assembly = Alki.create_assembly do
|
29
32
|
set :val, "one"
|
33
|
+
func :print do
|
34
|
+
puts val
|
35
|
+
end
|
36
|
+
|
30
37
|
group :g1 do
|
31
38
|
set :val, "two"
|
39
|
+
|
32
40
|
group :g2 do
|
33
41
|
func :print do
|
34
42
|
puts val
|
35
43
|
end
|
36
44
|
end
|
45
|
+
|
37
46
|
end
|
38
47
|
end
|
48
|
+
|
49
|
+
assembly.new.print
|
50
|
+
|
51
|
+
#output: one
|
52
|
+
|
39
53
|
assembly.new.g1.g2.print
|
40
54
|
|
41
55
|
#output: two
|
42
56
|
```
|
43
57
|
|
44
|
-
=== Loading groups
|
58
|
+
=== Loading groups (load)
|
45
59
|
|
46
60
|
Groups can also be loaded from other config files via the `load` command.
|
47
61
|
|
@@ -52,6 +66,7 @@ Alki do
|
|
52
66
|
end
|
53
67
|
```
|
54
68
|
|
69
|
+
.main code
|
55
70
|
```ruby
|
56
71
|
require 'alki'
|
57
72
|
assembly = Alki.create_assembly config_dir: 'config' do
|
@@ -69,6 +84,85 @@ assembly.new.print
|
|
69
84
|
Values
|
70
85
|
------
|
71
86
|
|
87
|
+
Values are how you add functionality to your Assembly. There are different types of values, but they
|
88
|
+
all share a number of common features.
|
89
|
+
|
90
|
+
### On-Demand
|
91
|
+
|
92
|
+
Values are only built when referenced, on demand. This means even if you have a very large assembly
|
93
|
+
only the things you actually use in a given run will be created, or often even `require`-d. It also
|
94
|
+
means that all values will automatically be built in the correct order to satisfy dependencies.
|
95
|
+
|
96
|
+
### Scope
|
97
|
+
|
98
|
+
When providing a block for a value, the block will be executed in a special context with some
|
99
|
+
additional helper methods.
|
100
|
+
|
101
|
+
The most important methods available are other elements that are "in scope". For example, a value can
|
102
|
+
reference a sibling element in the same group, or any value in any ancestor group. The order that
|
103
|
+
elements are defined does not effect what is in scope. All other elements are out of scope, but can
|
104
|
+
usually still be referenced by finding an ancestor group that 'is' in scope, and then drilling down
|
105
|
+
from there.
|
106
|
+
|
107
|
+
```ruby
|
108
|
+
require 'alki'
|
109
|
+
assembly = Alki.create_assembly config_dir: 'config' do
|
110
|
+
set :val1, "1"
|
111
|
+
group :main do
|
112
|
+
group :sub_group do
|
113
|
+
set :val2, "2"
|
114
|
+
end
|
115
|
+
|
116
|
+
set :values do
|
117
|
+
[
|
118
|
+
val1, # OK
|
119
|
+
# val2, # ERROR
|
120
|
+
sub_group.val2, # OK
|
121
|
+
val3, # OK
|
122
|
+
# val4, # ERROR
|
123
|
+
other_group.val4, #OK
|
124
|
+
].join('')
|
125
|
+
end
|
126
|
+
|
127
|
+
set :val3, "3"
|
128
|
+
end
|
129
|
+
|
130
|
+
group :other_group do
|
131
|
+
set :val4, "4"
|
132
|
+
end
|
133
|
+
|
134
|
+
end
|
135
|
+
puts assembly.new.main.values
|
136
|
+
|
137
|
+
#output: 1234
|
138
|
+
```
|
139
|
+
|
140
|
+
### Helpers
|
141
|
+
|
142
|
+
In addition to elements in scope, there are some helper methods that are always available in value
|
143
|
+
blocks.
|
144
|
+
|
145
|
+
[horizontal]
|
146
|
+
|
147
|
+
assembly:: This will return the root group of the assembly the element is defined in.
|
148
|
+
|
149
|
+
root:: This will return the root group of the 'top most' assembly being run. If only a single
|
150
|
+
assembly is being run, this will be the same as `assembly` but if the element being run is in
|
151
|
+
an assembly that has been mounted into another assembly, they will differ.
|
152
|
+
|
153
|
+
lookup(path):: This can be used to reference an element by a string path (using periods (`.`) to
|
154
|
+
drill down into groups). If called directly it will lookup using the local scope. It is also available
|
155
|
+
as a method on all groups, so `assembly.lookup(path)` would lookup an element starting from the root
|
156
|
+
of the assembly.
|
157
|
+
|
158
|
+
lazy(path):: This works the same as `lookup`, but with an important difference: Instead of doing the
|
159
|
+
lookup immediately, it will instead return a "proxy" object, which will do the lookup the first time
|
160
|
+
a method is called on the proxy object, and then delegate all method calls to the actual element. This
|
161
|
+
can be used to handle circular references in services.
|
162
|
+
|
163
|
+
Value Types
|
164
|
+
-----------
|
165
|
+
|
72
166
|
There are four types of elements loosely categorized as "values".
|
73
167
|
|
74
168
|
### Basic Values (set)
|
@@ -162,7 +256,7 @@ assembly.new.main_logger << "hello"
|
|
162
256
|
#output: hello
|
163
257
|
```
|
164
258
|
|
165
|
-
|
259
|
+
## Overlays (overlay)
|
166
260
|
|
167
261
|
Overlays are a way to intercept and transform calls made to all services in a given group or it's
|
168
262
|
sub-groups.
|
@@ -171,24 +265,29 @@ Overlays are often most useful in groups where all services adhere to a common i
|
|
171
265
|
can be used to perform aspect oriented programming like logging, validation, or access controls.
|
172
266
|
|
173
267
|
|
174
|
-
|
268
|
+
## Assemblies (assembly)
|
175
269
|
|
176
270
|
Other assemblies can be mounted into your Assembly using the `assembly` command.
|
177
271
|
|
178
|
-
The first argument is what
|
179
|
-
is the name of the assembly. This should be formatted like a require string (relative path but
|
272
|
+
The first argument is what the element should be named in the parent assembly. The optional second argument
|
273
|
+
is the name of the assembly to be mounted. This should be formatted like a require string (relative path but
|
180
274
|
no `.rb`) and will default to the value of the first argument. If a classified version of that name
|
181
|
-
can't be found,
|
275
|
+
can't be found, Alki will attempt to `require` it, and then look for it again.
|
182
276
|
|
183
277
|
```ruby
|
184
278
|
require 'alki'
|
279
|
+
|
280
|
+
# Creates OtherAssembly
|
185
281
|
Alki.create_assembly name: 'other_assembly' do
|
186
282
|
set :val, "one"
|
187
283
|
|
284
|
+
# This is invalid as there is no such element as 'val2'
|
188
285
|
set :invalid_val2 do
|
189
286
|
val2
|
190
287
|
end
|
191
288
|
|
289
|
+
# Normally, this would also be invalid, but if mounted
|
290
|
+
# in an assembly that has a 'val2' element, this works.
|
192
291
|
set :root_val2 do
|
193
292
|
root.val2
|
194
293
|
end
|
@@ -196,13 +295,15 @@ end
|
|
196
295
|
|
197
296
|
Alki.create_assembly name: 'main_assembly' do
|
198
297
|
set :val2, "two"
|
298
|
+
# Mounts OtherAssembly as 'other'
|
199
299
|
assembly :other, 'other_assembly'
|
200
300
|
end
|
201
301
|
instance = MainAssembly.new
|
202
302
|
puts instance.other.val
|
203
303
|
#output: one
|
204
304
|
|
205
|
-
#
|
305
|
+
# Even though val2 exists in MainAssembly, it is not directly accessibly to elements
|
306
|
+
# within OtherAssembly
|
206
307
|
begin
|
207
308
|
puts instance.other.invalid_val2
|
208
309
|
rescue => e
|
@@ -210,7 +311,7 @@ rescue => e
|
|
210
311
|
end
|
211
312
|
# output: undefined local variable or method 'val2'
|
212
313
|
|
213
|
-
# This works, because root returns the root assembly
|
314
|
+
# This works, because root returns the root assembly, which has a 'val2' element
|
214
315
|
puts instance.other.root_val2
|
215
316
|
#output: two
|
216
317
|
```
|
data/doc/{index.ad → index.adoc}
RENAMED
@@ -1,15 +1,16 @@
|
|
1
1
|
Alki
|
2
2
|
====
|
3
|
+
:toc:
|
3
4
|
|
4
5
|
Alki is a framework for creating projects that are modular, testable, and well organized.
|
5
6
|
|
6
7
|
It's goal is to remove uncertainty and friction when building Ruby projects, allowing developers to focus on implementing business logic.
|
7
8
|
|
8
9
|
:leveloffset: 1
|
9
|
-
include::projects.
|
10
|
+
include::projects.adoc[]
|
10
11
|
|
11
12
|
:leveloffset: 1
|
12
|
-
include::assemblies.
|
13
|
+
include::assemblies.adoc[]
|
13
14
|
|
14
15
|
:leveloffset: 1
|
15
|
-
include::assembly_dsl.
|
16
|
+
include::assembly_dsl.adoc[]
|
@@ -58,7 +58,7 @@ Alki do
|
|
58
58
|
|
59
59
|
def main_data
|
60
60
|
assembly_path = data[:prefix] ? data[:prefix].dup : []
|
61
|
-
{scope: {assembly: assembly_path, root: []}, overlays: []}
|
61
|
+
{scope: {assembly: assembly_path, root: [], config_dir: (assembly_path + [:config_dir])}, overlays: []}
|
62
62
|
end
|
63
63
|
|
64
64
|
def override
|
data/lib/alki/test.rb
CHANGED
@@ -1,5 +1,4 @@
|
|
1
|
-
require
|
2
|
-
Bundler.setup(:default,:test)
|
1
|
+
Bundler.require(:test)
|
3
2
|
require 'minitest/autorun'
|
4
3
|
require 'alki/dsl'
|
5
4
|
|
@@ -41,8 +40,8 @@ unless $LOAD_PATH.include? Alki::Test.lib_dir
|
|
41
40
|
$LOAD_PATH.unshift Alki::Test.lib_dir
|
42
41
|
end
|
43
42
|
|
44
|
-
|
43
|
+
test_helper = File.join(Alki::Test.tests_root,'test_helper.rb')
|
45
44
|
|
46
|
-
if File.exists?
|
47
|
-
require
|
45
|
+
if File.exists? test_helper
|
46
|
+
require test_helper
|
48
47
|
end
|
data/lib/alki/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: alki
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.8.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Matt Edlefsen
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2016-12-
|
11
|
+
date: 2016-12-10 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -103,14 +103,14 @@ files:
|
|
103
103
|
- ".gitignore"
|
104
104
|
- Gemfile
|
105
105
|
- LICENSE.txt
|
106
|
-
- README.
|
106
|
+
- README.adoc
|
107
107
|
- Rakefile
|
108
108
|
- alki.gemspec
|
109
109
|
- config/dsls.rb
|
110
|
-
- doc/assemblies.
|
111
|
-
- doc/assembly_dsl.
|
112
|
-
- doc/index.
|
113
|
-
- doc/projects.
|
110
|
+
- doc/assemblies.adoc
|
111
|
+
- doc/assembly_dsl.adoc
|
112
|
+
- doc/index.adoc
|
113
|
+
- doc/projects.adoc
|
114
114
|
- lib/alki.rb
|
115
115
|
- lib/alki/assembly.rb
|
116
116
|
- lib/alki/assembly_builder.rb
|
@@ -126,6 +126,7 @@ files:
|
|
126
126
|
- lib/alki/dsls/assembly_types/overlay.rb
|
127
127
|
- lib/alki/dsls/assembly_types/value.rb
|
128
128
|
- lib/alki/dsls/service.rb
|
129
|
+
- lib/alki/feature_test.rb
|
129
130
|
- lib/alki/overlay_delegator.rb
|
130
131
|
- lib/alki/override_builder.rb
|
131
132
|
- lib/alki/service_delegator.rb
|