alki 0.9.1 → 0.10.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (43) hide show
  1. checksums.yaml +4 -4
  2. data/README.adoc +8 -88
  3. data/alki.gemspec +2 -2
  4. data/exe/alki +2 -1
  5. data/lib/alki/assembly/builder.rb +29 -23
  6. data/lib/alki/assembly/executor.rb +57 -31
  7. data/lib/alki/assembly/{handler_base.rb → handler.rb} +1 -1
  8. data/lib/alki/assembly/instance.rb +9 -2
  9. data/lib/alki/assembly/type.rb +19 -0
  10. data/lib/alki/assembly/types/assembly.rb +1 -0
  11. data/lib/alki/assembly/types/factory.rb +2 -2
  12. data/lib/alki/assembly/types/func.rb +2 -2
  13. data/lib/alki/assembly/types/group.rb +19 -3
  14. data/lib/alki/assembly/types/override.rb +0 -7
  15. data/lib/alki/assembly/types/proc_value.rb +2 -2
  16. data/lib/alki/assembly/types/service.rb +24 -13
  17. data/lib/alki/assembly.rb +7 -6
  18. data/lib/alki/dsls/assembly.rb +3 -4
  19. data/lib/alki/dsls/assembly_group.rb +47 -26
  20. data/lib/alki/dsls/assembly_type.rb +4 -14
  21. data/lib/alki/execution/context.rb +17 -20
  22. data/lib/alki/execution/context_class_builder.rb +16 -2
  23. data/lib/alki/execution/helpers.rb +29 -0
  24. data/lib/alki/execution/reference.rb +18 -0
  25. data/lib/alki/execution/value_helpers.rb +14 -0
  26. data/lib/alki/overlay_info.rb +1 -1
  27. data/lib/alki/override_builder.rb +3 -3
  28. data/lib/alki/version.rb +1 -1
  29. data/lib/alki_loader.rb +2 -0
  30. data/test/feature/alki_test.rb +3 -5
  31. data/test/feature/example_test.rb +1 -4
  32. data/test/feature/overlays_test.rb +34 -0
  33. data/test/feature/pseudo_elements_test.rb +1 -1
  34. data/test/feature/reference_overlays_test.rb +24 -0
  35. data/test/feature/tags_test.rb +77 -0
  36. data/test/feature_test_helper.rb +34 -0
  37. data/test/integration/dsls/assembly_test.rb +2 -2
  38. data/test/integration/dsls/assembly_type_test.rb +1 -1
  39. data/test/integration/dsls/service_dsl_test.rb +1 -1
  40. metadata +16 -16
  41. data/config/dsls.rb +0 -4
  42. data/lib/alki/execution/value_context.rb +0 -23
  43. data/lib/alki/reloadable_delegator.rb +0 -17
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: bc1b79ca08e965916ecbd78625d9635f9b11868c
4
- data.tar.gz: 7d847de049a43edefa043d07ef4d64160c625407
3
+ metadata.gz: bc042cd47800b613d12e02456c24d25afc170f7b
4
+ data.tar.gz: 1ab703cbc5c5458d181f3b8d2a4c357d4d9c4056
5
5
  SHA512:
6
- metadata.gz: 05ffaa08ff5d51121f127ee2db0cc01238031b1b0ff6f7e0c1a95eedab5cd551e6733c991ea54a7058cc308468843b97591e40fdbac5c19b005317fbaddd5614
7
- data.tar.gz: a1db4bc72926268f1d1ccb789215c903bfd83a0e165816a98777fa15bf5ab70f230a2a35854f94ebf62df8cb0810f9f7b3a2c1fc09bc1cd3cac0d468964b148b
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 writing Ruby projects, providing a powerful dependency injection system with
5
- helpers for testing, creating executables, and easy to use libraries.
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 the time tested software engineering concepts such as
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
- Documentation can be found at https://github.com/alki-project/alki/blob/master/doc/index.adoc
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 created a couple of files, but the
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.3", '>= 0.3.3'
25
- spec.add_dependency "alki-support", "~> 0.6"
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?){ ENV['#{env_name}'] == 'development' }", match: /^\s*set :development?/, after: 'Alki do'
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 opts[:primary_config]
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','assembly.rb')) ||
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::Dsl.register_dir @config_dir, 'alki/dsls/assembly', dsl_opts
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(name = nil)
77
- name ||= 'assembly'
85
+ def load_assembly_file
78
86
  if @config_dir
79
- assembly_config_path = File.join(@config_dir,"#{name}.rb")
80
- if File.exists? assembly_config_path
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)[:class]
97
+ @definition = Alki::Dsl.build('alki/dsls/assembly', dsl_opts, &blk)
93
98
  end
94
99
 
95
100
  def dsl_opts
96
- opts = {config_dir: @config_dir}
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
- definition.is_a?(String) ?
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,overlays)
9
+ def initialize(assembly,meta)
10
10
  @assembly = assembly
11
- @overlays = overlays
11
+ @meta = meta
12
12
  @data = {}
13
13
  @semaphore = Monitor.new
14
14
  @lookup_cache = {}
15
15
  @call_cache = {}
16
16
  @context_cache = {}
17
- @processed_overlays = false
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
- if cache_entry
33
- if cache_entry.status == :building
34
- raise "Circular element reference found: #{path.join(".")}"
35
- end
36
- else
37
- @semaphore.synchronize do
38
- cache_entry = @call_cache[path]
39
- unless cache_entry
40
- cache_entry = @call_cache[path] = Alki::Execution::CacheEntry.new
41
- action = lookup(path)
42
- if action[:build]
43
- build_meta = meta.merge(building: path.join('.'))
44
- build_action = action[:build].merge(scope: action[:scope],modules: action[:modules])
45
- call_value(*process_action(build_action),build_meta,[action])
46
- end
47
- cache_entry.finish *process_action(action)
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 process_overlays
66
- unless @processed_overlays
67
- @processed_overlays = true
69
+ def process_meta
70
+ unless @processed_meta
71
+ @processed_meta = true
68
72
  @data[:overlays] = {}
69
- @overlays.each do |(from,info)|
70
- target = canonical_path(from,info.target) or
71
- raise InvalidPathError.new("Invalid overlay target #{info.target.join('.')}")
72
- overlay = info.overlay
73
- if overlay.is_a?(Array)
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
- process_overlays
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}")
@@ -1,6 +1,6 @@
1
1
  module Alki
2
2
  module Assembly
3
- class HandlerBase
3
+ class Handler
4
4
  def initialize(elem,data,key=nil)
5
5
  @elem = elem
6
6
  @data = data
@@ -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
- @obj = nil
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
- Alki::Support.load_class(@assembly_module).raw_instance self, *@args
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
@@ -73,6 +73,7 @@ Alki do
73
73
  end
74
74
 
75
75
  def update_scope(data,scope=data[:scope])
76
+ scope[:root] = []
76
77
  add_parent_path scope, data
77
78
  add_original scope, data
78
79
  end
@@ -1,11 +1,11 @@
1
1
  Alki do
2
- require 'alki/execution/value_context'
2
+ require 'alki/execution/value_helpers'
3
3
 
4
4
  attr :block
5
5
 
6
6
  output do
7
7
  {
8
- modules: [Alki::Execution::ValueContext],
8
+ modules: [Alki::Execution::ValueHelpers],
9
9
  scope: data[:scope],
10
10
  build: {
11
11
  methods: {
@@ -1,10 +1,10 @@
1
1
  Alki do
2
- require 'alki/execution/value_context'
2
+ require 'alki/execution/value_helpers'
3
3
 
4
4
  attr :block
5
5
  output do
6
6
  {
7
- modules: [Alki::Execution::ValueContext],
7
+ modules: [Alki::Execution::ValueHelpers],
8
8
  scope: data[:scope],
9
9
  proc: block
10
10
  }
@@ -1,14 +1,30 @@
1
1
  Alki do
2
- require 'alki/execution/context'
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.empty? || target.shift == key.to_sym
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::Context],
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/value_context'
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::ValueContext],
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/value_context'
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] = overlays.inject(__build__) do |val,(overlay,args)|
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::ValueContext],
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
- all_overlays = overlays+overrides_info[:overlays]+[update_instance_overlay]
25
- executor = Executor.new(assembly, all_overlays)
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 overlays
39
- self.definition.overlays
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::Support.load_class("alki/assembly/types/#{type}").new *args
46
+ Alki.load("alki/assembly/types/#{type}").new *args
46
47
  end
47
48
  end
48
49
  end