alki 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +23 -0
- data/Gemfile +7 -0
- data/LICENSE.txt +22 -0
- data/README.md +4 -0
- data/Rakefile +29 -0
- data/alki.gemspec +24 -0
- data/lib/alki/class_builder.rb +41 -0
- data/lib/alki/dsl_builder.rb +43 -0
- data/lib/alki/group_builder.rb +25 -0
- data/lib/alki/group_dsl.rb +98 -0
- data/lib/alki/loader.rb +32 -0
- data/lib/alki/overlay_delegator.rb +33 -0
- data/lib/alki/package.rb +33 -0
- data/lib/alki/package_builder.rb +2 -0
- data/lib/alki/package_executor.rb +120 -0
- data/lib/alki/package_processor.rb +167 -0
- data/lib/alki/service_delegator.rb +14 -0
- data/lib/alki/standard_package.rb +19 -0
- data/lib/alki/test.rb +28 -0
- data/lib/alki/util.rb +35 -0
- data/lib/alki/version.rb +3 -0
- data/lib/alki.rb +27 -0
- data/test/feature/create_package_test.rb +17 -0
- data/test/fixtures/config.rb +6 -0
- data/test/fixtures/example/config/handlers.rb +29 -0
- data/test/fixtures/example/config/package.rb +35 -0
- data/test/fixtures/example/config/settings.rb +11 -0
- data/test/fixtures/example/lib/array_output.rb +11 -0
- data/test/fixtures/example/lib/echo_handler.rb +9 -0
- data/test/fixtures/example/lib/example.rb +3 -0
- data/test/fixtures/example/lib/num_handler.rb +11 -0
- data/test/fixtures/example/lib/range_handler.rb +11 -0
- data/test/fixtures/example/lib/switch_handler.rb +9 -0
- data/test/integration/class_builder_test.rb +130 -0
- data/test/integration/loader_test.rb +36 -0
- data/test/test_helper.rb +1 -0
- data/test/unit/application_settings_test.rb +56 -0
- data/test/unit/application_test.rb +159 -0
- data/test/unit/package_processor_test.rb +319 -0
- metadata +129 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: acebb8f2a073f60c659eb7b994778f3717c140c9
|
4
|
+
data.tar.gz: c6bf4c35dbe97001bfed4b772a84e811b7200b93
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 623bacc9055973a92a710f2a7fe7235cdea0da93d5f434445b9b931ccc2c4ea51f261ba6715f19d95a5bd90ac5b496e05ce3f0e127877d1e45814863b0bd03d2
|
7
|
+
data.tar.gz: f33554183dc94171bb8191908745f218cf6bc5215e2125a9d9de4fc9cce1708a25799670e00833050fa83d54201fb02fb4f290f665881094f598870761c5476e
|
data/.gitignore
ADDED
@@ -0,0 +1,23 @@
|
|
1
|
+
*.gem
|
2
|
+
*.rbc
|
3
|
+
.bundle
|
4
|
+
.config
|
5
|
+
.yardoc
|
6
|
+
Gemfile.lock
|
7
|
+
InstalledFiles
|
8
|
+
_yardoc
|
9
|
+
coverage
|
10
|
+
doc/
|
11
|
+
lib/bundler/man
|
12
|
+
pkg
|
13
|
+
rdoc
|
14
|
+
spec/reports
|
15
|
+
test/tmp
|
16
|
+
test/version_tmp
|
17
|
+
tmp
|
18
|
+
*.bundle
|
19
|
+
*.so
|
20
|
+
*.o
|
21
|
+
*.a
|
22
|
+
mkmf.log
|
23
|
+
*.iml
|
data/Gemfile
ADDED
data/LICENSE.txt
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2015 Matt Edlefsen
|
2
|
+
|
3
|
+
MIT License
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
6
|
+
a copy of this software and associated documentation files (the
|
7
|
+
"Software"), to deal in the Software without restriction, including
|
8
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
9
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
+
permit persons to whom the Software is furnished to do so, subject to
|
11
|
+
the following conditions:
|
12
|
+
|
13
|
+
The above copyright notice and this permission notice shall be
|
14
|
+
included in all copies or substantial portions of the Software.
|
15
|
+
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
19
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
data/Rakefile
ADDED
@@ -0,0 +1,29 @@
|
|
1
|
+
require "bundler/gem_tasks"
|
2
|
+
require 'rake/testtask'
|
3
|
+
|
4
|
+
Rake::TestTask.new do |t|
|
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]
|
data/alki.gemspec
ADDED
@@ -0,0 +1,24 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'alki/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = "alki"
|
8
|
+
spec.version = Alki::VERSION
|
9
|
+
spec.authors = ["Matt Edlefsen"]
|
10
|
+
spec.email = ["matt@xforty.com"]
|
11
|
+
spec.summary = %q{Base library for building applications.}
|
12
|
+
spec.description = %q{Base library for building applications. Provides tools for organizing and connection application units.}
|
13
|
+
spec.homepage = "https://gitlab.xforty.com/matt/base-alki"
|
14
|
+
spec.license = "MIT"
|
15
|
+
|
16
|
+
spec.files = `git ls-files -z`.split("\x0")
|
17
|
+
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
18
|
+
spec.bindir = 'exe'
|
19
|
+
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
20
|
+
spec.require_paths = ["lib"]
|
21
|
+
|
22
|
+
spec.add_development_dependency "bundler", "~> 1.6"
|
23
|
+
spec.add_development_dependency "rake", '~> 10.0'
|
24
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
require 'alki/dsl_builder'
|
2
|
+
|
3
|
+
module Alki
|
4
|
+
class ClassBuilder
|
5
|
+
def initialize(*dsl_factories)
|
6
|
+
@dsl_factories = dsl_factories.flatten
|
7
|
+
end
|
8
|
+
|
9
|
+
def build(name=nil,&blk)
|
10
|
+
self.class.build(name,@dsl_factories,&blk)
|
11
|
+
end
|
12
|
+
|
13
|
+
def self.build(name=nil,dsl_factories,&blk)
|
14
|
+
Class.new.tap do |c|
|
15
|
+
builder = -> {
|
16
|
+
Module.new.tap do |m|
|
17
|
+
m.define_singleton_method :klass do
|
18
|
+
c
|
19
|
+
end
|
20
|
+
end
|
21
|
+
}
|
22
|
+
m = DslBuilder.build(c,dsl_factories,
|
23
|
+
builder: builder,exec: :class_exec,
|
24
|
+
&blk)
|
25
|
+
c.include m
|
26
|
+
if name
|
27
|
+
*ans, ln = name.to_s.split(/::/)
|
28
|
+
parent = Object
|
29
|
+
ans.each do |a|
|
30
|
+
unless parent.const_defined? a
|
31
|
+
parent.const_set a, Module.new
|
32
|
+
end
|
33
|
+
parent = parent.const_get a
|
34
|
+
end
|
35
|
+
|
36
|
+
parent.const_set ln, c
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
@@ -0,0 +1,43 @@
|
|
1
|
+
module Alki
|
2
|
+
class DslBuilder
|
3
|
+
def initialize(*dsl_factories,builder: nil, exec: nil)
|
4
|
+
@builder = builder
|
5
|
+
@exec = exec
|
6
|
+
@dsl_factories = dsl_factories.flatten
|
7
|
+
end
|
8
|
+
|
9
|
+
def build(obj,&blk)
|
10
|
+
self.class.build(obj,@dsl_factories,
|
11
|
+
builder: @builder,
|
12
|
+
exec: @exec,
|
13
|
+
&blk)
|
14
|
+
end
|
15
|
+
|
16
|
+
def self.build(obj,dsl_factories,builder: nil, exec: nil, &blk)
|
17
|
+
builder ||= Object.method(:new)
|
18
|
+
exec ||= :instance_exec
|
19
|
+
unless dsl_factories.is_a?(Array)
|
20
|
+
dsl_factories = [dsl_factories]
|
21
|
+
end
|
22
|
+
builder = builder.call
|
23
|
+
dsls = []
|
24
|
+
dsl_factories.each do |dsl_factory|
|
25
|
+
if dsl_factory.respond_to? :new_dsl
|
26
|
+
dsl = dsl_factory.new_dsl obj
|
27
|
+
else
|
28
|
+
dsl = dsl_factory.new obj
|
29
|
+
end
|
30
|
+
dsl.dsl_methods.each do |method_name|
|
31
|
+
method = dsl.method(method_name)
|
32
|
+
builder.define_singleton_method method_name do |*args,&blk|
|
33
|
+
method.call *args, &blk
|
34
|
+
end
|
35
|
+
end
|
36
|
+
dsls << dsl
|
37
|
+
end
|
38
|
+
builder.send(exec,&blk)
|
39
|
+
dsls.each {|dsl| dsl.finalize if dsl.respond_to? :finalize }
|
40
|
+
builder
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
require 'alki/group_dsl'
|
2
|
+
require 'alki/dsl_builder'
|
3
|
+
|
4
|
+
module Alki
|
5
|
+
class GroupBuilder
|
6
|
+
def self.build(loader,obj = {},&dsl)
|
7
|
+
Alki::GroupBuilder.new(loader).build(obj,&dsl)
|
8
|
+
obj
|
9
|
+
end
|
10
|
+
|
11
|
+
def initialize(loader)
|
12
|
+
@loader = loader
|
13
|
+
@builder = Alki::DslBuilder.new(self)
|
14
|
+
end
|
15
|
+
|
16
|
+
def new_dsl(obj)
|
17
|
+
GroupDsl.new(obj,loader: @loader, group_builder: @builder)
|
18
|
+
end
|
19
|
+
|
20
|
+
def build(group={},&dsl)
|
21
|
+
@builder.build(group,&dsl)
|
22
|
+
group
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,98 @@
|
|
1
|
+
require 'alki/util'
|
2
|
+
|
3
|
+
module Alki
|
4
|
+
class GroupDsl
|
5
|
+
def initialize(root,group_builder:,loader:)
|
6
|
+
@root = root
|
7
|
+
@group_builder = group_builder
|
8
|
+
@loader = loader
|
9
|
+
end
|
10
|
+
|
11
|
+
def dsl_methods
|
12
|
+
[:set,:service,:factory,:load,:import,:group,:overlay,:clear_overlays]
|
13
|
+
end
|
14
|
+
|
15
|
+
def set(name,value=nil,&blk)
|
16
|
+
service name, &(blk || -> { value })
|
17
|
+
end
|
18
|
+
|
19
|
+
def service(name,&blk)
|
20
|
+
name = name.to_sym
|
21
|
+
@root[name] = {
|
22
|
+
type: :service,
|
23
|
+
block: blk
|
24
|
+
}
|
25
|
+
end
|
26
|
+
|
27
|
+
def factory(name,&blk)
|
28
|
+
name = name.to_sym
|
29
|
+
@root[name] = {
|
30
|
+
type: :factory,
|
31
|
+
block: blk
|
32
|
+
}
|
33
|
+
end
|
34
|
+
|
35
|
+
def import(name)
|
36
|
+
instance_exec &@loader.load(name.to_s)
|
37
|
+
end
|
38
|
+
|
39
|
+
def load(name)
|
40
|
+
group(name.to_sym) do
|
41
|
+
import(name)
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
def package(name,pkg,klass=nil,&blk)
|
46
|
+
if pkg.is_a? String
|
47
|
+
require pkg
|
48
|
+
if klass == nil
|
49
|
+
pkg = Alki::Util.classify(pkg)
|
50
|
+
else
|
51
|
+
pkg = klass
|
52
|
+
end
|
53
|
+
end
|
54
|
+
if pkg.is_a? Class
|
55
|
+
pkg = pkg.new
|
56
|
+
end
|
57
|
+
if pkg.response_to? :package_definition
|
58
|
+
pkg = pkg.package_definition
|
59
|
+
end
|
60
|
+
unless pkg.is_a? Hash
|
61
|
+
raise "Invalid package: #{pkg.inspect}"
|
62
|
+
end
|
63
|
+
name = name.to_sym
|
64
|
+
overrides = {}
|
65
|
+
@group_builder.build(overrides,&blk) if blk
|
66
|
+
overrides[:original] = {
|
67
|
+
type: :package,
|
68
|
+
children: pkg,
|
69
|
+
overrides: {}
|
70
|
+
}
|
71
|
+
@root[name] = {
|
72
|
+
type: :package,
|
73
|
+
children: pkg,
|
74
|
+
overrides: overrides
|
75
|
+
}
|
76
|
+
end
|
77
|
+
|
78
|
+
def group(name,&blk)
|
79
|
+
name = name.to_sym
|
80
|
+
children = {}
|
81
|
+
@group_builder.build(children,&blk)
|
82
|
+
@root[name] = {
|
83
|
+
type: :group,
|
84
|
+
children: children
|
85
|
+
}
|
86
|
+
end
|
87
|
+
|
88
|
+
def overlay(&blk)
|
89
|
+
@root['overlays'] ||= []
|
90
|
+
@root['overlays'] << blk
|
91
|
+
end
|
92
|
+
|
93
|
+
def clear_overlays
|
94
|
+
@root['overlays'] ||= []
|
95
|
+
@root['overlays'] << :clear
|
96
|
+
end
|
97
|
+
end
|
98
|
+
end
|
data/lib/alki/loader.rb
ADDED
@@ -0,0 +1,32 @@
|
|
1
|
+
module Alki
|
2
|
+
class Loader
|
3
|
+
def self.load(config_file)
|
4
|
+
Fiber.new do
|
5
|
+
Kernel.load config_file
|
6
|
+
Thread.current[:alki_loader_current]
|
7
|
+
end.resume
|
8
|
+
end
|
9
|
+
|
10
|
+
def initialize(root_dir)
|
11
|
+
@root_dir = root_dir
|
12
|
+
end
|
13
|
+
|
14
|
+
def load_all
|
15
|
+
Dir[File.join(@root_dir,'**','*.rb')].inject({}) do |h,path|
|
16
|
+
file = path.gsub(File.join(@root_dir,''),'').gsub(/\.rb$/,'')
|
17
|
+
h.merge!(file => Loader.load(path))
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
def load(file)
|
22
|
+
Loader.load File.expand_path("#{file}.rb",@root_dir)
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
module Kernel
|
28
|
+
def Alki(&blk)
|
29
|
+
Thread.current[:alki_loader_current] = blk if blk
|
30
|
+
::Alki
|
31
|
+
end
|
32
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
module Alki
|
2
|
+
class OverlayDelegator
|
3
|
+
def initialize(name,obj,overlay)
|
4
|
+
@name = name
|
5
|
+
@obj = obj
|
6
|
+
@overlay = overlay
|
7
|
+
@key = :"#{obj.object_id}:#{overlay.object_id}"
|
8
|
+
end
|
9
|
+
|
10
|
+
def respond_to_missing(method,include_private = false)
|
11
|
+
unless Thread.current[@key]
|
12
|
+
Thread.current[@key] = true
|
13
|
+
if @overlay.respond_to? :overlay_respond_to?
|
14
|
+
@overlay.overlay_respond_to? @obj, method, include_private
|
15
|
+
else
|
16
|
+
@obj.respond_to? method, include_private
|
17
|
+
end
|
18
|
+
Thread.current[@key] = false
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
def method_missing(method,*args,&blk)
|
23
|
+
if Thread.current[@key]
|
24
|
+
res = @obj.send method, *args, &blk
|
25
|
+
else
|
26
|
+
Thread.current[@key] = true
|
27
|
+
res = @overlay.call @name, @obj, method, *args, &blk
|
28
|
+
Thread.current[@key] = false
|
29
|
+
end
|
30
|
+
res
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
data/lib/alki/package.rb
ADDED
@@ -0,0 +1,33 @@
|
|
1
|
+
require 'alki/package_executor'
|
2
|
+
require 'alki/package_processor'
|
3
|
+
|
4
|
+
module Alki
|
5
|
+
class Package
|
6
|
+
def initialize(package_definition)
|
7
|
+
@def = package_definition
|
8
|
+
@cache = {}
|
9
|
+
end
|
10
|
+
|
11
|
+
def root
|
12
|
+
@root ||= __executor__.call @def, @cache, []
|
13
|
+
end
|
14
|
+
|
15
|
+
def package_definition
|
16
|
+
@def
|
17
|
+
end
|
18
|
+
|
19
|
+
def respond_to_missing?(name,include_all)
|
20
|
+
root.respond_to? name
|
21
|
+
end
|
22
|
+
|
23
|
+
def method_missing(name,*args,&blk)
|
24
|
+
root.send name, *args, &blk
|
25
|
+
end
|
26
|
+
|
27
|
+
private
|
28
|
+
|
29
|
+
def __executor__
|
30
|
+
@executor ||= Alki::PackageExecutor.new Alki::PackageProcessor.new
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,120 @@
|
|
1
|
+
require 'alki/service_delegator'
|
2
|
+
require 'alki/overlay_delegator'
|
3
|
+
|
4
|
+
module Alki
|
5
|
+
class PackageExecutor
|
6
|
+
def initialize(processor)
|
7
|
+
@processor = processor
|
8
|
+
end
|
9
|
+
|
10
|
+
def call(pkg,cache,path,*args,&blk)
|
11
|
+
elem = @processor.lookup(pkg,path)
|
12
|
+
triple = [pkg,cache,elem]
|
13
|
+
case elem[:type]
|
14
|
+
when :service
|
15
|
+
service triple, path, *args
|
16
|
+
when :factory
|
17
|
+
factory triple, path, *args, &blk
|
18
|
+
when :group
|
19
|
+
group triple, *args
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
def service(triple,path)
|
24
|
+
pkg,cache,elem = triple
|
25
|
+
unless cache[path]
|
26
|
+
with_scope_context(triple) do |ctx,blk|
|
27
|
+
cache[path] = apply_overlays triple,path, ctx.instance_exec(&blk)
|
28
|
+
end
|
29
|
+
end
|
30
|
+
cache[path]
|
31
|
+
end
|
32
|
+
|
33
|
+
def apply_overlays((pkg,cache,elem),path,obj)
|
34
|
+
elem[:overlays].inject(obj) do |obj,overlay_elem|
|
35
|
+
unless cache[overlay_elem[:block]]
|
36
|
+
with_scope_context([pkg,cache,overlay_elem]) do |ctx,blk|
|
37
|
+
cache[overlay_elem[:block]] = ctx.instance_exec(&blk)
|
38
|
+
end
|
39
|
+
end
|
40
|
+
local_path = path[overlay_elem[:scope][:root].size..-1].join('.')
|
41
|
+
Alki::OverlayDelegator.new local_path,obj, cache[overlay_elem[:block]]
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
def factory(triple,path,*args,&blk)
|
46
|
+
pkg,cache,elem = triple
|
47
|
+
unless cache[path]
|
48
|
+
with_scope_context(triple) do |ctx,blk|
|
49
|
+
cache[path] = ctx.instance_exec(&blk)
|
50
|
+
end
|
51
|
+
end
|
52
|
+
cache[path].call *args, &blk
|
53
|
+
end
|
54
|
+
|
55
|
+
def group((pkg,cache,elem))
|
56
|
+
proc = -> (name,*args,&blk) {
|
57
|
+
call pkg, cache, elem[:children][name], *args, &blk
|
58
|
+
}
|
59
|
+
|
60
|
+
GroupContext.new(proc,elem[:children].keys)
|
61
|
+
end
|
62
|
+
|
63
|
+
def with_scope_context((pkg,cache,elem))
|
64
|
+
proc = -> (name,*args,&blk) {
|
65
|
+
call pkg, cache, elem[:scope][name], *args, &blk
|
66
|
+
}
|
67
|
+
|
68
|
+
yield ServiceContext.new(proc,elem[:scope].keys), elem[:block]
|
69
|
+
end
|
70
|
+
|
71
|
+
class Context
|
72
|
+
def initialize(executor,scope)
|
73
|
+
@executor = executor
|
74
|
+
@scope = scope
|
75
|
+
end
|
76
|
+
|
77
|
+
def respond_to_missing?(name,include_all)
|
78
|
+
@scope.include? name
|
79
|
+
end
|
80
|
+
|
81
|
+
def method_missing(name,*args,&blk)
|
82
|
+
if @scope.include? name
|
83
|
+
@executor.call name, *args, &blk
|
84
|
+
else
|
85
|
+
super
|
86
|
+
end
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
class ServiceContext < Context
|
91
|
+
def lookup(path)
|
92
|
+
unless path.is_a?(String) or path.is_a?(Symbol)
|
93
|
+
raise ArgumentError.new("lookup can only take Strings or Symbols")
|
94
|
+
end
|
95
|
+
path.to_s.split('.').inject(self) do |group,name|
|
96
|
+
raise "Invalid lookup path" unless group.is_a? Context
|
97
|
+
group.send name.to_sym
|
98
|
+
end
|
99
|
+
end
|
100
|
+
|
101
|
+
def lazy(path)
|
102
|
+
unless path.is_a?(String) or path.is_a?(Symbol)
|
103
|
+
raise ArgumentError.new("lazy can only take Strings or Symbols")
|
104
|
+
end
|
105
|
+
Alki::ServiceDelegator.new root, path
|
106
|
+
end
|
107
|
+
end
|
108
|
+
|
109
|
+
class GroupContext < Context
|
110
|
+
def lookup(path)
|
111
|
+
unless path.is_a?(String) or path.is_a?(Symbol)
|
112
|
+
raise ArgumentError.new("lookup can only take Strings or Symbols")
|
113
|
+
end
|
114
|
+
path.to_s.split('.').inject(self) do |group,name|
|
115
|
+
group.send name.to_sym
|
116
|
+
end
|
117
|
+
end
|
118
|
+
end
|
119
|
+
end
|
120
|
+
end
|