alki 0.12.0 → 0.12.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/Gemfile +1 -0
- data/README.adoc +132 -20
- data/Rakefile +2 -27
- data/alki.gemspec +1 -3
- data/bin/bundler +17 -0
- data/bin/rake +17 -0
- data/doc/assemblies.adoc +2 -3
- data/doc/assembly_dsl.adoc +191 -30
- data/doc/{projects.adoc → executables.adoc} +40 -16
- data/doc/index.adoc +4 -3
- data/lib/alki.rb +3 -0
- data/lib/alki/assembly.rb +4 -34
- data/lib/alki/assembly/builder.rb +3 -3
- data/lib/alki/assembly/instance.rb +31 -5
- data/lib/alki/assembly/instance_builder.rb +48 -0
- data/lib/alki/assembly/meta/overlay.rb +7 -2
- data/lib/alki/assembly/meta/tags.rb +4 -4
- data/lib/alki/assembly/types.rb +9 -0
- data/lib/alki/assembly/types/assembly.rb +3 -3
- data/lib/alki/assembly/types/group.rb +16 -25
- data/lib/alki/assembly/types/original.rb +12 -0
- data/lib/alki/assembly/types/override.rb +0 -2
- data/lib/alki/assembly/types/service.rb +4 -4
- data/lib/alki/circular_reference_error.rb +25 -0
- data/lib/alki/dsls/assembly.rb +1 -1
- data/lib/alki/dsls/assembly_group.rb +28 -12
- data/lib/alki/execution/context_class_builder.rb +1 -1
- data/lib/alki/execution/helpers.rb +4 -4
- data/lib/alki/execution/overlay_map.rb +37 -0
- data/lib/alki/execution/tag_map.rb +42 -0
- data/lib/alki/executor.rb +140 -0
- data/lib/alki/override_builder.rb +30 -24
- data/lib/alki/overrides.rb +4 -0
- data/lib/alki/version.rb +1 -1
- data/test/feature/mounts_test.rb +15 -0
- data/test/feature/multithreading_test.rb +0 -3
- data/test/feature/overlays_test.rb +2 -2
- data/test/feature/overrides_test.rb +26 -1
- data/test/feature/references_test.rb +35 -0
- data/test/feature/try_mounts_test.rb +23 -0
- data/test/feature/values_test.rb +14 -0
- data/test/feature_test_helper.rb +1 -0
- data/test/fixtures/example/config/assembly.rb +17 -8
- data/test/fixtures/example/config/handlers.rb +10 -5
- data/test/fixtures/example/lib/dsls/num_handler.rb +2 -2
- data/test/fixtures/example/lib/example/array_output.rb +13 -0
- data/test/fixtures/example/lib/example/echo_handler.rb +11 -0
- data/test/fixtures/example/lib/example/log_overlay.rb +12 -0
- data/test/fixtures/example/lib/example/num_handler.rb +13 -0
- data/test/fixtures/example/lib/example/range_handler.rb +13 -0
- data/test/fixtures/example/lib/example/switch_handler.rb +11 -0
- metadata +39 -44
- data/lib/alki/assembly/executor.rb +0 -137
- data/test/fixtures/example/lib/array_output.rb +0 -11
- data/test/fixtures/example/lib/echo_handler.rb +0 -9
- data/test/fixtures/example/lib/log_overlay.rb +0 -10
- data/test/fixtures/example/lib/num_handler.rb +0 -11
- data/test/fixtures/example/lib/range_handler.rb +0 -11
- data/test/fixtures/example/lib/switch_handler.rb +0 -9
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: c3e661fb5cb33a76f94430ca79d62dae03fb2527
|
4
|
+
data.tar.gz: 4c288022884681ff99906ac0787cc4c82bb25c1d
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: c3c44874d4ce17e340d25224b8c5131bc00d4f9595bd09bdf85f22aab2d296a493d1cee68e5f97ffa7794c2e8859bb6bb7cfb18e40c8af5727ecc6777982ba69
|
7
|
+
data.tar.gz: f86c11fed68fb98600efb661fb6c1c255212690e18f42bf7fa2bef59df220c5f469d9d2a461a94f7e59c765b0473e605ee7abcd95d6fbbe86758d9a399fdc239
|
data/Gemfile
CHANGED
data/README.adoc
CHANGED
@@ -1,34 +1,146 @@
|
|
1
1
|
# What is Alki?
|
2
2
|
|
3
|
-
Alki is a small
|
4
|
-
|
3
|
+
Alki is a small library to help organize and scale your Ruby project, so you can focus on the
|
4
|
+
important stuff. It can be used alongside frameworks such as Ruby on Rails.
|
5
5
|
|
6
|
-
|
7
|
-
implementing business logic. It can be used alongside other frameworks such as Ruby on Rails.
|
6
|
+
Some high level features:
|
8
7
|
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
8
|
+
* Easily manage objects and dependencies
|
9
|
+
* Enables writing reusable and testable code
|
10
|
+
* Developer console (built on pry)
|
11
|
+
* Automatic code reloading on changes in development
|
12
|
+
* Powerful DSL toolkit
|
13
|
+
* Extensible
|
14
14
|
|
15
|
-
Further documentation can be found at https://github.com/alki-project/alki/blob/master/doc/index.adoc
|
16
15
|
|
17
|
-
|
16
|
+
## Installation
|
18
17
|
|
19
|
-
|
18
|
+
Add this line to your application's Gemfile:
|
20
19
|
|
21
|
-
|
20
|
+
```ruby
|
21
|
+
gem 'alki'
|
22
|
+
```
|
23
|
+
|
24
|
+
And then execute:
|
25
|
+
|
26
|
+
$ bundle
|
27
|
+
|
28
|
+
Or install it yourself as:
|
29
|
+
|
30
|
+
$ gem install alki
|
31
|
+
|
32
|
+
## Introduction
|
33
|
+
|
34
|
+
[NOTE]
|
35
|
+
Full "todo" example can be found https://github.com/alki-project/alki-examples/tree/master/todo[here]
|
36
|
+
|
37
|
+
Alki simplifies project organization by pulling out all of the "connective tissue"
|
38
|
+
that connects our classes and modules together, and puts them into a special object
|
39
|
+
called an Assembly.
|
40
|
+
|
41
|
+
There are many ways to use Assemblies, but the most common is to have a single
|
42
|
+
Assembly for you project. For example, if you hade a "todo" command line utility
|
43
|
+
project that you wanted to use Alki with, all you would need to do to create
|
44
|
+
an Assembly is add this file.
|
22
45
|
|
23
|
-
|
46
|
+
.lib/todo.rb
|
47
|
+
```ruby
|
48
|
+
require 'alki'
|
49
|
+
Alki.project_assembly!
|
50
|
+
```
|
24
51
|
|
25
|
-
|
26
|
-
`alki` command line tool can also be used to automate the process. Project names
|
27
|
-
should be given in lowercase using underscores and forward slashes as separators.
|
52
|
+
This will create a module called `Todo` that is an empty assembly:
|
28
53
|
|
29
|
-
.Example project
|
30
54
|
```
|
31
|
-
$
|
32
|
-
|
55
|
+
$ bundle exec irb -Ilib
|
56
|
+
2.4.0 :001 > require 'todo'
|
57
|
+
=> true
|
58
|
+
2.4.0 :002 > todo = Todo.new
|
59
|
+
=> #<Todo:21964520>
|
60
|
+
```
|
61
|
+
|
62
|
+
### Defining Elements
|
63
|
+
|
64
|
+
Add things to the assembly requires an assembly definition file. By convention this is
|
65
|
+
named `config/assembly.rb` and is built using a simple DSL. There are
|
66
|
+
a handful of different element types in Assemblies. Below are a few of the
|
67
|
+
most common. Full documentation of the DSL can be found
|
68
|
+
https://github.com/alki-project/alki/blob/master/doc/assembly_dsl.adoc[here]
|
69
|
+
|
70
|
+
.config/assembly.rb
|
71
|
+
```ruby
|
72
|
+
Alki do
|
73
|
+
group :settings do <1>
|
74
|
+
set(:home) { ENV['HOME'] } <2>
|
75
|
+
set(:db_path) { ENV['TODO_DB_PATH'] || File.join(home,'.todo_db2') }
|
76
|
+
set :prompt, 'todo> '
|
77
|
+
end
|
78
|
+
|
79
|
+
service :interface do <3>
|
80
|
+
require 'todo/readline_interface'
|
81
|
+
Todo::ReadlineInterface.new settings.prompt, handler
|
82
|
+
end
|
83
|
+
|
84
|
+
service :handler do
|
85
|
+
require 'todo/command_handler'
|
86
|
+
Todo::CommandHandler.new db
|
87
|
+
end
|
88
|
+
|
89
|
+
service :db do
|
90
|
+
require 'todo/store_db'
|
91
|
+
Todo::StoreDb.new file_store
|
92
|
+
end
|
93
|
+
|
94
|
+
service :file_store do
|
95
|
+
require 'todo/json_file_store'
|
96
|
+
Todo::JsonFileStore.new settings.db_path
|
97
|
+
end
|
98
|
+
end
|
33
99
|
```
|
100
|
+
<1> `group` allows bundling together subelements and can be moved to their own files
|
101
|
+
<2> `set` defines simple values
|
102
|
+
<3> `service` defines our main application objects
|
103
|
+
|
104
|
+
Any element can be accessed directly from the assembly object.
|
105
|
+
|
106
|
+
```
|
107
|
+
$ bundle exec irb -Ilib
|
108
|
+
2.4.0 :001 > require 'todo'
|
109
|
+
=> true
|
110
|
+
2.4.0 :002 > todo = Todo.new
|
111
|
+
=> #<Todo:21964520>
|
112
|
+
2.4.0 :003 > todo.settings.prompt
|
113
|
+
=> 'todo> '
|
114
|
+
```
|
115
|
+
|
116
|
+
The 'alki-console' tool can also be used to quickly work with assemblies.
|
117
|
+
Add `gem 'alki-console'` to your Gemspec and run `bundle --binstubs`.
|
118
|
+
|
119
|
+
```
|
120
|
+
$ bin/alki-console
|
121
|
+
todo> settings.prompt
|
122
|
+
=> 'todo> '
|
123
|
+
```
|
124
|
+
|
125
|
+
### Creating an executable
|
126
|
+
|
127
|
+
Read more about creating executables with Alki
|
128
|
+
https://github.com/alki-project/alki/blob/master/doc/executables.adoc[here]
|
129
|
+
|
130
|
+
In the todo example, it's a CLI utility so it requires an executable.
|
131
|
+
|
132
|
+
.exe/todo
|
133
|
+
```ruby
|
134
|
+
require 'todo'
|
135
|
+
Todo.new.interface.run
|
136
|
+
```
|
137
|
+
|
138
|
+
## Further Documentation
|
139
|
+
|
140
|
+
Further documentation can be found https://github.com/alki-project/alki/blob/master/doc/index.adoc[here]
|
141
|
+
|
142
|
+
Example projects can be found https://github.com/alki-project/alki-examples[here]
|
143
|
+
|
144
|
+
## Authors
|
34
145
|
|
146
|
+
Written by Matt Edlefsen
|
data/Rakefile
CHANGED
@@ -1,29 +1,4 @@
|
|
1
1
|
require "bundler/gem_tasks"
|
2
|
-
require '
|
2
|
+
require 'alki/testing/tasks'
|
3
3
|
|
4
|
-
|
5
|
-
t.name = 'test:unit'
|
6
|
-
t.pattern = "test/unit/*_test.rb"
|
7
|
-
end
|
8
|
-
|
9
|
-
Rake::TestTask.new do |t|
|
10
|
-
t.name = 'test:feature'
|
11
|
-
t.pattern = "test/feature/*_test.rb"
|
12
|
-
end
|
13
|
-
|
14
|
-
Rake::TestTask.new do |t|
|
15
|
-
t.name = 'test:integration'
|
16
|
-
t.pattern = "test/integration/*_test.rb"
|
17
|
-
end
|
18
|
-
|
19
|
-
Rake::TestTask.new do |t|
|
20
|
-
t.name = 'test:page'
|
21
|
-
t.pattern = "test/page/*_test.rb"
|
22
|
-
end
|
23
|
-
|
24
|
-
Rake::TestTask.new do |t|
|
25
|
-
t.name = 'test'
|
26
|
-
t.pattern = "test/*/*_test.rb"
|
27
|
-
end
|
28
|
-
|
29
|
-
task default: [:test]
|
4
|
+
task default: [:test]
|
data/alki.gemspec
CHANGED
@@ -18,9 +18,7 @@ Gem::Specification.new do |spec|
|
|
18
18
|
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
19
19
|
spec.require_paths = ["lib"]
|
20
20
|
|
21
|
-
spec.
|
22
|
-
spec.add_development_dependency "rake", '~> 10.0'
|
23
|
-
spec.add_dependency "alki-dsl", "~> 0.5"
|
21
|
+
spec.add_dependency "alki-dsl", "~> 0.5", '>= 0.5.1'
|
24
22
|
spec.add_dependency "alki-support", "~> 0.7"
|
25
23
|
spec.add_dependency "concurrent-ruby", "~> 1.0"
|
26
24
|
spec.add_dependency "ice_nine", "~> 0.11"
|
data/bin/bundler
ADDED
@@ -0,0 +1,17 @@
|
|
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
ADDED
@@ -0,0 +1,17 @@
|
|
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")
|
data/doc/assemblies.adoc
CHANGED
@@ -17,7 +17,7 @@ Project Assemblies
|
|
17
17
|
Most of the time, a project will have a single assembly, so Alki makes having a single project wide
|
18
18
|
assembly especially easy.
|
19
19
|
|
20
|
-
First
|
20
|
+
First, in your project's `lib` directory create a ruby file for your assembly. If your assembly is
|
21
21
|
to be called `MyAssembly`, create `lib/my_assembly.rb`. If it's namespaced put it in a subdirectory
|
22
22
|
as usual (i.e. `MyModule::MyAssembly` would go in `lib/my_module/my_assembly.rb`).
|
23
23
|
|
@@ -126,7 +126,6 @@ The limitiation of this is that it can only override basic values. To override m
|
|
126
126
|
a block can be given to `new` allowing the full assembly DSL.
|
127
127
|
|
128
128
|
```ruby
|
129
|
-
require 'alki'
|
130
129
|
class MyLogger
|
131
130
|
def initialize(io)
|
132
131
|
@io = io
|
@@ -150,4 +149,4 @@ instance.util.logger.info "test"
|
|
150
149
|
|
151
150
|
One thing of note is that elements from the assembly are accessible in overrides via the `original`
|
152
151
|
method, as seen above. This can also be used to access the original versions of elements that have
|
153
|
-
been overriden.
|
152
|
+
been overriden.
|
data/doc/assembly_dsl.adoc
CHANGED
@@ -2,7 +2,7 @@ Assembly DSL
|
|
2
2
|
============
|
3
3
|
:toc:
|
4
4
|
|
5
|
-
Building Assemblies is done via a DSL
|
5
|
+
Building Assemblies is done via a small DSL
|
6
6
|
|
7
7
|
Groups (group)
|
8
8
|
--------------
|
@@ -23,8 +23,7 @@ puts assembly.new.sub_group.val
|
|
23
23
|
#output: hello world
|
24
24
|
```
|
25
25
|
|
26
|
-
Scoping is also done by group, so that an element will be found by searching through parent groups
|
27
|
-
it is found.
|
26
|
+
Scoping is also done by group, so that an element will be found by searching through parent groups.
|
28
27
|
|
29
28
|
```ruby
|
30
29
|
require 'alki'
|
@@ -213,8 +212,7 @@ puts assembly.new.greet "Matt"
|
|
213
212
|
|
214
213
|
Services are the key element Assemblies are typically made up of. Like the block form of `set`,
|
215
214
|
`service` takes a name and block, which will be evaluated once on-demand and the result cached.
|
216
|
-
|
217
|
-
by overlays, whereas basic values are not.
|
215
|
+
Whereas `set` is a lightweight element for simple values, `service` provides more functionality.
|
218
216
|
|
219
217
|
Commonly a service will require the file that defines a class, and then constructs an instance of
|
220
218
|
that class.
|
@@ -235,9 +233,13 @@ assembly.new.logger << "hello\n"
|
|
235
233
|
### Factories (factory)
|
236
234
|
|
237
235
|
Factories are a mix between services and funcs. Like services, they take a block which is evaluated
|
238
|
-
once. Unlike services though, that block must return a callable
|
239
|
-
|
240
|
-
a factory
|
236
|
+
once. Unlike services though, that block must return a callable "builder" (like a Proc).
|
237
|
+
|
238
|
+
If a factory is referenced as a service (i.e. no arguments) it returns a factory object
|
239
|
+
that responds to either `#call` or `#new` and will call the builder in turn.
|
240
|
+
|
241
|
+
If a factory is instead referenced like a method (i.e. with arguments) it will
|
242
|
+
call the builder directly.
|
241
243
|
|
242
244
|
```ruby
|
243
245
|
require 'alki'
|
@@ -249,6 +251,8 @@ assembly = Alki.create_assembly do
|
|
249
251
|
|
250
252
|
service :main_logger do
|
251
253
|
logger STDOUT
|
254
|
+
# -or-
|
255
|
+
logger.call STDOUT
|
252
256
|
end
|
253
257
|
end
|
254
258
|
assembly.new.main_logger << "hello\n"
|
@@ -256,29 +260,23 @@ assembly.new.main_logger << "hello\n"
|
|
256
260
|
#output: hello
|
257
261
|
```
|
258
262
|
|
259
|
-
## Overlays (overlay)
|
260
|
-
|
261
|
-
Overlays are a way to intercept and transform calls made to all services in a given group or it's
|
262
|
-
sub-groups.
|
263
|
-
|
264
|
-
Overlays are often most useful in groups where all services adhere to a common interface, and overlays
|
265
|
-
can be used to perform aspect oriented programming like logging, validation, or access controls.
|
266
|
-
|
267
263
|
|
268
264
|
## Mounting Assemblies (mount)
|
269
265
|
|
270
266
|
Other assemblies can be mounted into your Assembly using the `mount` command.
|
271
267
|
|
272
|
-
The first argument is what the element should be named in the parent assembly.
|
273
|
-
|
274
|
-
|
275
|
-
|
268
|
+
The first argument is what the element should be named in the parent assembly.
|
269
|
+
The optional second argument is the assembly to be mounted.
|
270
|
+
This can either be the assembly module,
|
271
|
+
or be a "require" string (relative path but no `.rb`).
|
272
|
+
It defaults to the element name.
|
273
|
+
If a string, Alki will attempt to `require` it, and then look for a matching constant.
|
274
|
+
|
276
275
|
|
277
276
|
```ruby
|
278
277
|
require 'alki'
|
279
278
|
|
280
|
-
|
281
|
-
Alki.create_assembly name: 'other_assembly' do
|
279
|
+
other_assembly = Alki.create_assembly do
|
282
280
|
set :val, "one"
|
283
281
|
|
284
282
|
# This is invalid as there is no such element as 'val2'
|
@@ -293,12 +291,11 @@ Alki.create_assembly name: 'other_assembly' do
|
|
293
291
|
end
|
294
292
|
end
|
295
293
|
|
296
|
-
Alki.create_assembly
|
294
|
+
assembly = Alki.create_assembly do
|
297
295
|
set :val2, "two"
|
298
|
-
|
299
|
-
mount :other, 'other_assembly'
|
296
|
+
mount :other, other_assembly
|
300
297
|
end
|
301
|
-
instance =
|
298
|
+
instance = assembly.new
|
302
299
|
puts instance.other.val
|
303
300
|
#output: one
|
304
301
|
|
@@ -322,22 +319,186 @@ automatically in scope for overrides.
|
|
322
319
|
|
323
320
|
```ruby
|
324
321
|
require 'alki'
|
325
|
-
Alki.create_assembly
|
322
|
+
other_assembly = Alki.create_assembly do
|
326
323
|
set :msg, nil
|
327
324
|
func :print do
|
328
325
|
puts msg
|
329
326
|
end
|
330
327
|
end
|
331
328
|
|
332
|
-
Alki.create_assembly
|
329
|
+
assembly = Alki.create_assembly do
|
333
330
|
set :val, "hello"
|
334
|
-
mount :other,
|
331
|
+
mount :other, other_assembly do
|
335
332
|
set :msg do
|
336
333
|
val
|
337
334
|
end
|
338
335
|
end
|
339
336
|
end
|
340
|
-
|
337
|
+
assembly.new.other.print
|
341
338
|
|
342
339
|
#output: hello
|
343
340
|
```
|
341
|
+
|
342
|
+
## Overlays and Tags
|
343
|
+
|
344
|
+
Overlays are a way to transparently wrap services. They work by taking the
|
345
|
+
name of a service or a group, in which case they are applied to all services in that group,
|
346
|
+
along with the name of an element to be used as the overlay, plus some optional arguments.
|
347
|
+
|
348
|
+
When the named service is built, the overlay element will be called (with `.call`), with
|
349
|
+
the built service object and the optional arguments, and it's result will be what's
|
350
|
+
returned.
|
351
|
+
|
352
|
+
Factories work well as overlay elements.
|
353
|
+
|
354
|
+
```ruby
|
355
|
+
require 'alki'
|
356
|
+
|
357
|
+
assembly = Alki.create_assembly do
|
358
|
+
overlay :greeting, :exclaim, 3
|
359
|
+
|
360
|
+
service :greeting do
|
361
|
+
'Hello World'
|
362
|
+
end
|
363
|
+
|
364
|
+
factory :exclaim do
|
365
|
+
-> (string,count) do
|
366
|
+
string + ('!' * count)
|
367
|
+
end
|
368
|
+
end
|
369
|
+
end
|
370
|
+
|
371
|
+
puts assembly.new.greeting
|
372
|
+
|
373
|
+
#output: Hello World!!!
|
374
|
+
```
|
375
|
+
|
376
|
+
### Tags (tag)
|
377
|
+
|
378
|
+
Tags are way of adding metadata to your elements. They can either be just a name, or
|
379
|
+
optionally carry a value
|
380
|
+
|
381
|
+
```ruby
|
382
|
+
require 'alki'
|
383
|
+
|
384
|
+
assembly = Alki.create_assembly do
|
385
|
+
tag :tag1, with_value: 123
|
386
|
+
service :tagged do
|
387
|
+
meta[:tags]
|
388
|
+
end
|
389
|
+
end
|
390
|
+
|
391
|
+
puts assembly.new.tagged
|
392
|
+
|
393
|
+
#output: {:with_value=>123, :tag1=>true}
|
394
|
+
```
|
395
|
+
|
396
|
+
Tags can be applied to groups to tag everything within that group
|
397
|
+
|
398
|
+
```ruby
|
399
|
+
require 'alki'
|
400
|
+
|
401
|
+
assembly = Alki.create_assembly do
|
402
|
+
tag :tag1
|
403
|
+
group :grp do
|
404
|
+
tag :tag2
|
405
|
+
service :tagged do
|
406
|
+
meta[:tags]
|
407
|
+
end
|
408
|
+
end
|
409
|
+
end
|
410
|
+
|
411
|
+
puts assembly.new.grp.tagged
|
412
|
+
|
413
|
+
#output: {:tag1=>true, :tag2=>true}
|
414
|
+
```
|
415
|
+
|
416
|
+
#### Overlaying tags (overlay_tag)
|
417
|
+
|
418
|
+
Instead of overlaying services directly, it's often useful to overlay all services
|
419
|
+
with a given tag.
|
420
|
+
|
421
|
+
```ruby
|
422
|
+
require 'alki'
|
423
|
+
|
424
|
+
assembly = Alki.create_assembly do
|
425
|
+
overlay_tag :exclaimed, :exclaim, 3
|
426
|
+
|
427
|
+
tag :exclaimed
|
428
|
+
service :greeting do
|
429
|
+
'Hello World'
|
430
|
+
end
|
431
|
+
|
432
|
+
factory :exclaim do
|
433
|
+
-> (string,count) do
|
434
|
+
string + ('!' * count)
|
435
|
+
end
|
436
|
+
end
|
437
|
+
end
|
438
|
+
|
439
|
+
puts assembly.new.greeting
|
440
|
+
|
441
|
+
#output: Hello World!!!
|
442
|
+
```
|
443
|
+
|
444
|
+
Factories can access the tags of the services their being called from, allowing you
|
445
|
+
to customize the build based on what tags are present
|
446
|
+
|
447
|
+
```ruby
|
448
|
+
require 'alki'
|
449
|
+
|
450
|
+
assembly = Alki.create_assembly do
|
451
|
+
overlay_tag :process, :process_string
|
452
|
+
|
453
|
+
tag :process, exclaim: 3
|
454
|
+
service :greeting do
|
455
|
+
'Hello World'
|
456
|
+
end
|
457
|
+
|
458
|
+
factory :process_string do
|
459
|
+
-> (string) do
|
460
|
+
if exclaim = meta[:tags][:exclaim]
|
461
|
+
string = string + ('!' * exclaim)
|
462
|
+
end
|
463
|
+
string
|
464
|
+
end
|
465
|
+
end
|
466
|
+
end
|
467
|
+
|
468
|
+
puts assembly.new.greeting
|
469
|
+
|
470
|
+
#output: Hello World!!!
|
471
|
+
```
|
472
|
+
|
473
|
+
Finally, tag overlays work even across assembly mounts, allowing overlays to
|
474
|
+
be defined in a library, and then applied by tagging services.
|
475
|
+
|
476
|
+
```ruby
|
477
|
+
require 'alki'
|
478
|
+
|
479
|
+
string_processor = Alki.create_assembly do
|
480
|
+
overlay_tag :process, :process_string
|
481
|
+
|
482
|
+
factory :process_string do
|
483
|
+
-> (string) do
|
484
|
+
if exclaim = meta[:tags][:exclaim]
|
485
|
+
string = string + ('!' * exclaim)
|
486
|
+
end
|
487
|
+
string
|
488
|
+
end
|
489
|
+
end
|
490
|
+
end
|
491
|
+
|
492
|
+
assembly = Alki.create_assembly do
|
493
|
+
mount :string_processor, string_processor
|
494
|
+
|
495
|
+
tag :process, exclaim: 3
|
496
|
+
service :greeting do
|
497
|
+
'Hello World'
|
498
|
+
end
|
499
|
+
end
|
500
|
+
|
501
|
+
puts assembly.new.greeting
|
502
|
+
|
503
|
+
#output: Hello World!!!
|
504
|
+
```
|