alki 0.9.1 → 0.10.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.adoc +8 -88
- data/alki.gemspec +2 -2
- data/exe/alki +2 -1
- data/lib/alki/assembly/builder.rb +29 -23
- data/lib/alki/assembly/executor.rb +57 -31
- data/lib/alki/assembly/{handler_base.rb → handler.rb} +1 -1
- data/lib/alki/assembly/instance.rb +9 -2
- data/lib/alki/assembly/type.rb +19 -0
- data/lib/alki/assembly/types/assembly.rb +1 -0
- data/lib/alki/assembly/types/factory.rb +2 -2
- data/lib/alki/assembly/types/func.rb +2 -2
- data/lib/alki/assembly/types/group.rb +19 -3
- data/lib/alki/assembly/types/override.rb +0 -7
- data/lib/alki/assembly/types/proc_value.rb +2 -2
- data/lib/alki/assembly/types/service.rb +24 -13
- data/lib/alki/assembly.rb +7 -6
- data/lib/alki/dsls/assembly.rb +3 -4
- data/lib/alki/dsls/assembly_group.rb +47 -26
- data/lib/alki/dsls/assembly_type.rb +4 -14
- data/lib/alki/execution/context.rb +17 -20
- data/lib/alki/execution/context_class_builder.rb +16 -2
- data/lib/alki/execution/helpers.rb +29 -0
- data/lib/alki/execution/reference.rb +18 -0
- data/lib/alki/execution/value_helpers.rb +14 -0
- data/lib/alki/overlay_info.rb +1 -1
- data/lib/alki/override_builder.rb +3 -3
- data/lib/alki/version.rb +1 -1
- data/lib/alki_loader.rb +2 -0
- data/test/feature/alki_test.rb +3 -5
- data/test/feature/example_test.rb +1 -4
- data/test/feature/overlays_test.rb +34 -0
- data/test/feature/pseudo_elements_test.rb +1 -1
- data/test/feature/reference_overlays_test.rb +24 -0
- data/test/feature/tags_test.rb +77 -0
- data/test/feature_test_helper.rb +34 -0
- data/test/integration/dsls/assembly_test.rb +2 -2
- data/test/integration/dsls/assembly_type_test.rb +1 -1
- data/test/integration/dsls/service_dsl_test.rb +1 -1
- metadata +16 -16
- data/config/dsls.rb +0 -4
- data/lib/alki/execution/value_context.rb +0 -23
- data/lib/alki/reloadable_delegator.rb +0 -17
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: bc042cd47800b613d12e02456c24d25afc170f7b
|
4
|
+
data.tar.gz: 1ab703cbc5c5458d181f3b8d2a4c357d4d9c4056
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: b85b7153906906aaabb7d3dfc18e6060765f68bcf3a2885972acbbbd1c3d6a01a15b5c112205dc8fa0f64cf8403f056dd9091fadc2849e3051806cb4fe3fb183
|
7
|
+
data.tar.gz: b4dabbf9b1b3514ae65e189334848768670839d4e086bb6160158154ece8b7041def60184036e819c15df41de971ebb126849c1db62cb52917014615995f0abd
|
data/README.adoc
CHANGED
@@ -1,19 +1,20 @@
|
|
1
1
|
# What is Alki?
|
2
|
-
:toc:
|
3
2
|
|
4
|
-
Alki is a small framework for
|
5
|
-
helpers for testing, creating executables, and
|
3
|
+
Alki is a small framework for Ruby that provides a powerful dependency injection and program
|
4
|
+
management system with helpers for testing, creating executables, and writing DSLs.
|
6
5
|
|
7
6
|
It's goal is to remove uncertainty and friction when building Ruby projects, allowing developers to focus on
|
8
7
|
implementing business logic. It can be used alongside other frameworks such as Ruby on Rails.
|
9
8
|
|
10
|
-
Alki tries to combine
|
9
|
+
Alki tries to combine time tested software engineering concepts such as
|
11
10
|
https://en.wikipedia.org/wiki/SOLID_(object-oriented_design)[SOLID],
|
12
11
|
and https://en.wikipedia.org/wiki/Inversion_of_control[Inversion of Control], with
|
13
12
|
Ruby style ease of use, DSLs, and
|
14
13
|
https://en.wikipedia.org/wiki/Convention_over_configuration[Convention over Configuration].
|
15
14
|
|
16
|
-
|
15
|
+
Further documentation can be found at https://github.com/alki-project/alki/blob/master/doc/index.adoc
|
16
|
+
|
17
|
+
Example projects can be found at https://github.com/alki-project/alki-examples
|
17
18
|
|
18
19
|
## Getting Started
|
19
20
|
|
@@ -21,94 +22,13 @@ Install from rubygems
|
|
21
22
|
|
22
23
|
gem install alki
|
23
24
|
|
24
|
-
Setting up Alki in your project requires only
|
25
|
+
Setting up Alki in your project requires only creating a couple of files, but the
|
25
26
|
`alki` command line tool can also be used to automate the process. Project names
|
26
27
|
should be given in lowercase using underscores and forward slashes as separators.
|
27
28
|
|
28
29
|
.Example project
|
29
30
|
```
|
30
31
|
$ cd <project dir>
|
31
|
-
$ alki init --console <project name>
|
32
|
+
$ alki init --addons console <project name>
|
32
33
|
```
|
33
|
-
## Example
|
34
|
-
|
35
|
-
To demonstrate the basic features of Alki, this will go through the creation of
|
36
|
-
a simple example project.
|
37
|
-
|
38
|
-
To get started, a new project should be created.
|
39
|
-
|
40
|
-
```
|
41
|
-
$ mkdir example
|
42
|
-
$ cd example
|
43
|
-
$ alki init --console example
|
44
|
-
```
|
45
|
-
|
46
|
-
### First Service
|
47
|
-
|
48
|
-
Open up `config/assembly.rb` in your favorite text editor and add a simple log
|
49
|
-
service as an example. The service definition should require the files it needs and
|
50
|
-
then construct an object.
|
51
|
-
|
52
|
-
.config/assembly.rb
|
53
|
-
```ruby
|
54
|
-
Alki do
|
55
|
-
mount :console, 'alki/console', name: 'example'
|
56
|
-
|
57
|
-
service :log do
|
58
|
-
require 'logger'
|
59
|
-
Logger.new STDERR
|
60
|
-
end
|
61
|
-
end
|
62
|
-
```
|
63
|
-
|
64
|
-
To test, we can open up the console and interact with our new service.
|
65
|
-
|
66
|
-
```bash
|
67
|
-
$ bin/console
|
68
|
-
example> log.info "test message"
|
69
|
-
I, [<timestamp>] INFO -- : test message
|
70
|
-
=> true
|
71
|
-
test> exit
|
72
|
-
```
|
73
|
-
|
74
|
-
### Adding Settings
|
75
|
-
|
76
|
-
Many times in a project there will end with a lot of configuration settings or magic
|
77
|
-
numbers sprinkled throughout your code, maybe pulled from `ENV` or just set directly
|
78
|
-
as constants. Alki provides a simple way to centralize them. By convention this is done
|
79
|
-
by creating a `config/settings.rb` and loading it into your Assembly.
|
80
|
-
|
81
|
-
To demonstrate we can pull the log io (`STDERR`) out of our main assembly and add it
|
82
|
-
to our settings.
|
83
|
-
|
84
|
-
.config/settings.rb
|
85
|
-
```ruby
|
86
|
-
Alki do
|
87
|
-
set :log_io, STDERR
|
88
|
-
end
|
89
|
-
```
|
90
|
-
Now we can load our settings file in our assembly config (`load :settings`) and use
|
91
|
-
the setting in our log service.
|
92
|
-
|
93
|
-
.config/assembly.rb
|
94
|
-
```ruby
|
95
|
-
Alki do
|
96
|
-
load :settings
|
97
|
-
mount :console, 'alki/console', name: 'example'
|
98
|
-
|
99
|
-
service :log do
|
100
|
-
require 'logger'
|
101
|
-
Logger.new settings.log_io
|
102
|
-
end
|
103
|
-
end
|
104
|
-
```
|
105
|
-
|
106
|
-
### Adding your own Classes
|
107
|
-
|
108
|
-
Generally, you're not just going to be using other people's classes. Alki doesn't have any requirements as to
|
109
|
-
where your classes need to go, but conventionally they can be placed under `lib/<project-name>/`.
|
110
|
-
|
111
|
-
The Alki style of writing a Class is to only `require` external libraries, or utility files in your class files.
|
112
|
-
All of the "glue" that ties your code together can instead be put in your assembly definition. This allows you
|
113
|
-
to modularize and loosely couple your programs.
|
114
34
|
|
data/alki.gemspec
CHANGED
@@ -21,6 +21,6 @@ Gem::Specification.new do |spec|
|
|
21
21
|
spec.add_development_dependency "bundler", "~> 1.6"
|
22
22
|
spec.add_development_dependency "rake", '~> 10.0'
|
23
23
|
spec.add_dependency "minitest", "~> 5.9", '>= 5.9.1'
|
24
|
-
spec.add_dependency "alki-dsl", "~> 0.
|
25
|
-
spec.add_dependency "alki-support", "~> 0.
|
24
|
+
spec.add_dependency "alki-dsl", "~> 0.4"
|
25
|
+
spec.add_dependency "alki-support", "~> 0.7"
|
26
26
|
end
|
data/exe/alki
CHANGED
@@ -102,7 +102,8 @@ if options[:addons].include? "reload"
|
|
102
102
|
|
103
103
|
env_name = project_name.tr('a-z/','A-Z_')+"_ENV"
|
104
104
|
fw.add_line primary_config_path, " mount(:reloader, 'alki/reload'){ set(:watch) { development? } }", match: /^\s*mount\(? *:reloader/, after: 'Alki do'
|
105
|
-
fw.add_line primary_config_path, " set(:development?){
|
105
|
+
fw.add_line primary_config_path, " set(:development?){ environment == 'development' }", match: /^\s*set\(? *:development\?/, after: 'Alki do'
|
106
|
+
fw.add_line primary_config_path, " set(:environment){ ENV['#{env_name}'] || 'development' }", match: /^\s*set\(? *:environment/, after: 'Alki do'
|
106
107
|
end
|
107
108
|
|
108
109
|
fw.write
|
@@ -11,6 +11,7 @@ module Alki
|
|
11
11
|
@assembly_name = nil
|
12
12
|
@definition = nil
|
13
13
|
@load_mode = :direct
|
14
|
+
@primary_config = 'assembly'
|
14
15
|
end
|
15
16
|
|
16
17
|
attr_reader :config_dir, :assembly_name, :definition
|
@@ -22,6 +23,9 @@ module Alki
|
|
22
23
|
def build(opts={},&blk)
|
23
24
|
@load_mode = opts[:load_mode] if opts[:load_mode]
|
24
25
|
build_assembly blk if blk
|
26
|
+
@primary_config = opts[:primary_config] if opts[:primary_config]
|
27
|
+
set_assembly_name opts[:name] if opts[:name]
|
28
|
+
setup_project_assembly opts[:project_assembly] if opts[:project_assembly]
|
25
29
|
if opts[:config_dir]
|
26
30
|
context = if opts[:project_assembly]
|
27
31
|
File.dirname opts[:project_assembly]
|
@@ -30,13 +34,11 @@ module Alki
|
|
30
34
|
end
|
31
35
|
@config_dir = File.expand_path opts[:config_dir], context
|
32
36
|
end
|
33
|
-
set_assembly_name opts[:name] if opts[:name]
|
34
|
-
setup_project_assembly opts[:project_assembly] if opts[:project_assembly]
|
35
37
|
register_config_directory if @config_dir
|
36
38
|
if blk
|
37
39
|
build_assembly blk
|
38
40
|
else
|
39
|
-
load_assembly_file
|
41
|
+
load_assembly_file
|
40
42
|
end
|
41
43
|
build_empty_assembly unless definition
|
42
44
|
build_class
|
@@ -44,16 +46,11 @@ module Alki
|
|
44
46
|
|
45
47
|
def setup_project_assembly(path)
|
46
48
|
root = Alki::Support.find_root(path) do |dir|
|
47
|
-
File.exists?(File.join(dir,'config',
|
49
|
+
File.exists?(File.join(dir,'config',"#{@primary_config}.rb")) ||
|
48
50
|
File.exists?(File.join(dir,'Gemfile')) ||
|
49
51
|
!Dir.glob(File.join(dir,'*.gemspec')).empty?
|
50
52
|
end
|
51
53
|
if root
|
52
|
-
unless @config_dir
|
53
|
-
config_dir = File.join(root,'config')
|
54
|
-
@config_dir = config_dir if File.exists? config_dir
|
55
|
-
end
|
56
|
-
|
57
54
|
unless @assembly_name
|
58
55
|
lib_dir = File.join(root,'lib')
|
59
56
|
name = Alki::Support.path_name path, lib_dir
|
@@ -62,6 +59,11 @@ module Alki
|
|
62
59
|
end
|
63
60
|
set_assembly_name name
|
64
61
|
end
|
62
|
+
|
63
|
+
unless @config_dir
|
64
|
+
config_dir = File.join(root,'config')
|
65
|
+
@config_dir = config_dir if File.exists? config_dir
|
66
|
+
end
|
65
67
|
end
|
66
68
|
end
|
67
69
|
|
@@ -69,18 +71,21 @@ module Alki
|
|
69
71
|
@assembly_name = name
|
70
72
|
end
|
71
73
|
|
74
|
+
def config_prefix
|
75
|
+
unless @assembly_name
|
76
|
+
raise "Can't use config directory without a name"
|
77
|
+
end
|
78
|
+
File.join(@assembly_name,'assembly_config')
|
79
|
+
end
|
80
|
+
|
72
81
|
def register_config_directory
|
73
|
-
Alki::
|
82
|
+
Alki::Loader.register @config_dir, builder: 'alki/dsls/assembly', name: config_prefix, **dsl_opts
|
74
83
|
end
|
75
84
|
|
76
|
-
def load_assembly_file
|
77
|
-
name ||= 'assembly'
|
85
|
+
def load_assembly_file
|
78
86
|
if @config_dir
|
79
|
-
|
80
|
-
|
81
|
-
@definition = assembly_config_path
|
82
|
-
true
|
83
|
-
end
|
87
|
+
@definition = File.join(config_prefix,@primary_config)
|
88
|
+
true
|
84
89
|
end
|
85
90
|
end
|
86
91
|
|
@@ -89,14 +94,17 @@ module Alki
|
|
89
94
|
end
|
90
95
|
|
91
96
|
def build_assembly(blk)
|
92
|
-
@definition = Alki::Dsl.build('alki/dsls/assembly', dsl_opts, &blk)
|
97
|
+
@definition = Alki::Dsl.build('alki/dsls/assembly', dsl_opts, &blk)
|
93
98
|
end
|
94
99
|
|
95
100
|
def dsl_opts
|
96
|
-
opts = {
|
101
|
+
opts = {}
|
97
102
|
if @assembly_name
|
98
|
-
opts[:prefix] = File.join(@assembly_name,'alki_config')
|
99
103
|
opts[:assembly_name] = @assembly_name
|
104
|
+
if @config_dir
|
105
|
+
opts[:config_dir] = @config_dir
|
106
|
+
opts[:prefix] = config_prefix
|
107
|
+
end
|
100
108
|
end
|
101
109
|
opts
|
102
110
|
end
|
@@ -122,9 +130,7 @@ module Alki
|
|
122
130
|
},
|
123
131
|
definition: {
|
124
132
|
body: ->{
|
125
|
-
|
126
|
-
Alki::Dsl.load(definition)[:class] :
|
127
|
-
definition
|
133
|
+
Alki.load definition
|
128
134
|
}
|
129
135
|
},
|
130
136
|
load_class: {
|
@@ -6,15 +6,15 @@ module Alki
|
|
6
6
|
InvalidPathError = Class.new(StandardError)
|
7
7
|
module Assembly
|
8
8
|
class Executor
|
9
|
-
def initialize(assembly,
|
9
|
+
def initialize(assembly,meta)
|
10
10
|
@assembly = assembly
|
11
|
-
@
|
11
|
+
@meta = meta
|
12
12
|
@data = {}
|
13
13
|
@semaphore = Monitor.new
|
14
14
|
@lookup_cache = {}
|
15
15
|
@call_cache = {}
|
16
16
|
@context_cache = {}
|
17
|
-
@
|
17
|
+
@processed_meta = false
|
18
18
|
end
|
19
19
|
|
20
20
|
def synchronize
|
@@ -28,26 +28,30 @@ module Alki
|
|
28
28
|
end
|
29
29
|
|
30
30
|
def execute(meta,path,args,blk)
|
31
|
+
cache_entry = nil
|
32
|
+
synchronize do
|
31
33
|
cache_entry = @call_cache[path]
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
34
|
+
end
|
35
|
+
if cache_entry
|
36
|
+
if cache_entry.status == :building
|
37
|
+
raise "Circular element reference found: #{path.join(".")}"
|
38
|
+
end
|
39
|
+
else
|
40
|
+
synchronize do
|
41
|
+
cache_entry = @call_cache[path]
|
42
|
+
unless cache_entry
|
43
|
+
cache_entry = @call_cache[path] = Alki::Execution::CacheEntry.new
|
44
|
+
action = lookup(path)
|
45
|
+
if action[:build]
|
46
|
+
build_meta = meta.merge(building: path.join('.'))
|
47
|
+
build_meta.merge!(action[:meta]) if action[:meta]
|
48
|
+
build_action = action[:build].merge(scope: action[:scope],modules: action[:modules])
|
49
|
+
call_value(*process_action(build_action),build_meta,[action])
|
48
50
|
end
|
51
|
+
cache_entry.finish *process_action(action)
|
49
52
|
end
|
50
53
|
end
|
54
|
+
end
|
51
55
|
call_value(cache_entry.type,cache_entry.value,meta,args,blk)
|
52
56
|
end
|
53
57
|
|
@@ -62,25 +66,47 @@ module Alki
|
|
62
66
|
|
63
67
|
private
|
64
68
|
|
65
|
-
def
|
66
|
-
unless @
|
67
|
-
@
|
69
|
+
def process_meta
|
70
|
+
unless @processed_meta
|
71
|
+
@processed_meta = true
|
68
72
|
@data[:overlays] = {}
|
69
|
-
@
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
overlay = canonical_path(from,info.overlay) or
|
75
|
-
raise InvalidPathError.new("Invalid overlay path #{info.overlay.join('.')}")
|
73
|
+
@data[:tags] = {}
|
74
|
+
@meta.each do |(from,type,info)|
|
75
|
+
case type
|
76
|
+
when :overlay then process_overlay from, info
|
77
|
+
when :tags then process_tags from, info
|
76
78
|
end
|
77
|
-
(@data[:overlays][target]||=[]) << [overlay,info.args]
|
78
79
|
end
|
79
80
|
end
|
80
81
|
end
|
81
82
|
|
83
|
+
def process_tags(from,tags)
|
84
|
+
tags.each do |tag|
|
85
|
+
(@data[:tags][tag]||=[]) << from
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
def process_overlay(from,info)
|
90
|
+
target_path = info.target.dup
|
91
|
+
if target_path.last.to_s.start_with?('%')
|
92
|
+
tag = target_path.pop
|
93
|
+
end
|
94
|
+
if target_path == []
|
95
|
+
target_path = [:root]
|
96
|
+
end
|
97
|
+
target = canonical_path(from,target_path) or
|
98
|
+
raise InvalidPathError.new("Invalid overlay target #{info.target.join('.')}")
|
99
|
+
target = target.dup.push tag if tag
|
100
|
+
overlay = info.overlay
|
101
|
+
if overlay.is_a?(Array)
|
102
|
+
overlay = canonical_path(from,info.overlay) or
|
103
|
+
raise InvalidPathError.new("Invalid overlay path #{info.overlay.join('.')}")
|
104
|
+
end
|
105
|
+
(@data[:overlays][target]||=[]) << [info.type, overlay, info.args]
|
106
|
+
end
|
107
|
+
|
82
108
|
def lookup(path)
|
83
|
-
|
109
|
+
process_meta
|
84
110
|
@lookup_cache[path] ||= lookup_elem(path).tap do |elem|
|
85
111
|
unless elem
|
86
112
|
raise InvalidPathError.new("Invalid path #{path.inspect}")
|
@@ -7,6 +7,7 @@ module Alki
|
|
7
7
|
def initialize(assembly_module,args)
|
8
8
|
@assembly_module = assembly_module
|
9
9
|
@args = args
|
10
|
+
@version = 0
|
10
11
|
end
|
11
12
|
|
12
13
|
def __reload__
|
@@ -14,7 +15,7 @@ module Alki
|
|
14
15
|
did_something = @obj.__reload__
|
15
16
|
end
|
16
17
|
if did_something != false && @obj
|
17
|
-
|
18
|
+
__setobj__ nil
|
18
19
|
did_something = true
|
19
20
|
end
|
20
21
|
if did_something
|
@@ -24,12 +25,18 @@ module Alki
|
|
24
25
|
end
|
25
26
|
|
26
27
|
def __setobj__(obj)
|
28
|
+
@version += 1
|
27
29
|
@obj = obj
|
28
30
|
end
|
29
31
|
|
32
|
+
def __version__
|
33
|
+
@version
|
34
|
+
end
|
35
|
+
|
30
36
|
def __getobj__
|
31
37
|
unless @obj
|
32
|
-
|
38
|
+
# Will call __setobj__
|
39
|
+
Alki.load(@assembly_module).raw_instance self, *@args
|
33
40
|
end
|
34
41
|
@obj
|
35
42
|
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
module Alki
|
2
|
+
module Assembly
|
3
|
+
class Type
|
4
|
+
def index(*args)
|
5
|
+
handler(args).index
|
6
|
+
end
|
7
|
+
|
8
|
+
def output(*args)
|
9
|
+
handler(args).output
|
10
|
+
end
|
11
|
+
|
12
|
+
private
|
13
|
+
|
14
|
+
def handler(args)
|
15
|
+
self.class::Handler.new(self,*args)
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -1,11 +1,11 @@
|
|
1
1
|
Alki do
|
2
|
-
require 'alki/execution/
|
2
|
+
require 'alki/execution/value_helpers'
|
3
3
|
|
4
4
|
attr :block
|
5
5
|
|
6
6
|
output do
|
7
7
|
{
|
8
|
-
modules: [Alki::Execution::
|
8
|
+
modules: [Alki::Execution::ValueHelpers],
|
9
9
|
scope: data[:scope],
|
10
10
|
build: {
|
11
11
|
methods: {
|
@@ -1,14 +1,30 @@
|
|
1
1
|
Alki do
|
2
|
-
require 'alki/execution/
|
2
|
+
require 'alki/execution/helpers'
|
3
3
|
|
4
4
|
attr(:children){ {} }
|
5
5
|
|
6
6
|
index do
|
7
7
|
update_scope children, data[:prefix], data[:scope]
|
8
8
|
|
9
|
+
data[:tags] = data[:tags].inject({}) do |tags,(tag,tagged)|
|
10
|
+
tagged.each do |path|
|
11
|
+
if path.empty? || path[0] == key.to_sym
|
12
|
+
tags[tag] = (tags[tag]||[]) | [path[1..-1]]
|
13
|
+
end
|
14
|
+
end
|
15
|
+
tags
|
16
|
+
end
|
17
|
+
|
9
18
|
data[:overlays] = data[:overlays].inject({}) do |no,(target,overlays)|
|
10
19
|
target = target.dup
|
11
|
-
if target.
|
20
|
+
if target.size == 1 && target[0].to_s.start_with?('%')
|
21
|
+
tags = data[:tags][target[0].to_s[1..-1].to_sym]
|
22
|
+
if tags
|
23
|
+
tags.each do |target|
|
24
|
+
(no[target]||=[]).push *overlays
|
25
|
+
end
|
26
|
+
end
|
27
|
+
elsif target.empty? || target.shift == key.to_sym
|
12
28
|
(no[target]||=[]).push *overlays
|
13
29
|
end
|
14
30
|
no
|
@@ -23,7 +39,7 @@ Alki do
|
|
23
39
|
{
|
24
40
|
full_scope: update_scope(children, data[:prefix], data[:scope]),
|
25
41
|
scope: update_scope(children,data[:prefix]),
|
26
|
-
modules: [Alki::Execution::
|
42
|
+
modules: [Alki::Execution::Helpers],
|
27
43
|
proc: ->{self}
|
28
44
|
}
|
29
45
|
end
|
@@ -10,13 +10,6 @@ Alki do
|
|
10
10
|
|
11
11
|
if main_child && override_child
|
12
12
|
(data[:main][:scope]||={}).merge! (data[:override][:scope]||{})
|
13
|
-
data[:main][:overlays]||={}
|
14
|
-
if data[:override][:overlays]
|
15
|
-
data[:override][:overlays].each do |target,overlays|
|
16
|
-
(data[:main][:overlays][target]||=[]).push *overlays
|
17
|
-
end
|
18
|
-
end
|
19
|
-
data[:override][:overlays]=data[:main][:overlays].dup
|
20
13
|
Alki::Assembly::Types::Override.new main_child, override_child
|
21
14
|
elsif main_child
|
22
15
|
data.replace data[:main]
|
@@ -1,5 +1,5 @@
|
|
1
1
|
Alki do
|
2
|
-
require 'alki/execution/
|
2
|
+
require 'alki/execution/value_helpers'
|
3
3
|
|
4
4
|
attr :proc
|
5
5
|
|
@@ -11,7 +11,7 @@ Alki do
|
|
11
11
|
},
|
12
12
|
proc: ->(desc) {desc[:value] = __build__}
|
13
13
|
},
|
14
|
-
modules: [Alki::Execution::
|
14
|
+
modules: [Alki::Execution::ValueHelpers],
|
15
15
|
scope: data[:scope]
|
16
16
|
}
|
17
17
|
end
|
@@ -1,26 +1,37 @@
|
|
1
1
|
Alki do
|
2
|
-
require 'alki/execution/
|
2
|
+
require 'alki/execution/value_helpers'
|
3
3
|
|
4
4
|
attr :block
|
5
5
|
|
6
6
|
output do
|
7
|
-
overlays = data[:overlays][[]]||[]
|
7
|
+
overlays = (data[:overlays][[]]||[]).group_by(&:first)
|
8
|
+
value_overlays = overlays[:value]||[]
|
9
|
+
reference_overlays = overlays[:reference]||[]
|
10
|
+
methods = {
|
11
|
+
__build__: block,
|
12
|
+
__apply_overlays__: -> obj, overlays {
|
13
|
+
overlays.inject(obj) do |val,(_,overlay,args)|
|
14
|
+
overlay = __raw_root__.lookup(overlay) if overlay.is_a?(Array)
|
15
|
+
if !overlay.respond_to?(:call) && overlay.respond_to?(:new)
|
16
|
+
overlay = overlay.method(:new)
|
17
|
+
end
|
18
|
+
overlay.call val, *args
|
19
|
+
end
|
20
|
+
}
|
21
|
+
}
|
22
|
+
unless reference_overlays.empty?
|
23
|
+
methods[:__process_reference__] = -> ref {
|
24
|
+
__apply_overlays__ ref, reference_overlays
|
25
|
+
}
|
26
|
+
end
|
8
27
|
{
|
9
28
|
build: {
|
10
|
-
methods:
|
11
|
-
__build__: block
|
12
|
-
},
|
29
|
+
methods: methods,
|
13
30
|
proc: -> (elem) {
|
14
|
-
elem[:value] =
|
15
|
-
overlay = root.lookup(overlay) if overlay.is_a?(Array)
|
16
|
-
if !overlay.respond_to?(:call) && overlay.respond_to?(:new)
|
17
|
-
overlay = overlay.method(:new)
|
18
|
-
end
|
19
|
-
overlay.call val, *args
|
20
|
-
end
|
31
|
+
elem[:value] = __apply_overlays__ __build__, value_overlays
|
21
32
|
},
|
22
33
|
},
|
23
|
-
modules: [Alki::Execution::
|
34
|
+
modules: [Alki::Execution::ValueHelpers],
|
24
35
|
scope: data[:scope],
|
25
36
|
}
|
26
37
|
end
|
data/lib/alki/assembly.rb
CHANGED
@@ -16,13 +16,14 @@ module Alki
|
|
16
16
|
override_root = overrides_info[:root] || build(:group)
|
17
17
|
|
18
18
|
assembly = build :assembly, root, override_root
|
19
|
-
update_instance_overlay = [[],OverlayInfo.new(
|
19
|
+
update_instance_overlay = [[],:overlay, OverlayInfo.new(
|
20
|
+
:value,
|
20
21
|
[:assembly_instance],
|
21
22
|
->obj{instance.__setobj__ obj; instance},
|
22
23
|
[]
|
23
24
|
)]
|
24
|
-
|
25
|
-
executor = Executor.new(assembly,
|
25
|
+
all_meta = meta+overrides_info[:meta]+[update_instance_overlay]
|
26
|
+
executor = Executor.new(assembly, all_meta)
|
26
27
|
|
27
28
|
override_root.children[:assembly_instance] = build(:service,->{
|
28
29
|
root
|
@@ -35,14 +36,14 @@ module Alki
|
|
35
36
|
self.definition.root
|
36
37
|
end
|
37
38
|
|
38
|
-
def
|
39
|
-
self.definition.
|
39
|
+
def meta
|
40
|
+
self.definition.meta
|
40
41
|
end
|
41
42
|
|
42
43
|
private
|
43
44
|
|
44
45
|
def build(type,*args)
|
45
|
-
Alki
|
46
|
+
Alki.load("alki/assembly/types/#{type}").new *args
|
46
47
|
end
|
47
48
|
end
|
48
49
|
end
|