alki 0.12.0 → 0.12.1
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/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
|
+
```
|