gamefic 3.4.0 → 3.5.0
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/CHANGELOG.md +14 -0
- data/README.md +1 -1
- data/lib/gamefic/active/epic.rb +1 -0
- data/lib/gamefic/active.rb +4 -0
- data/lib/gamefic/chapter.rb +25 -42
- data/lib/gamefic/command.rb +40 -1
- data/lib/gamefic/dispatcher.rb +5 -31
- data/lib/gamefic/entity.rb +26 -0
- data/lib/gamefic/narrative.rb +9 -5
- data/lib/gamefic/plot.rb +5 -0
- data/lib/gamefic/proxy.rb +46 -0
- data/lib/gamefic/query/base.rb +28 -12
- data/lib/gamefic/query/general.rb +3 -12
- data/lib/gamefic/query/result.rb +4 -1
- data/lib/gamefic/query/scoped.rb +1 -18
- data/lib/gamefic/query/text.rb +13 -12
- data/lib/gamefic/response.rb +65 -34
- data/lib/gamefic/scanner/base.rb +44 -0
- data/lib/gamefic/scanner/fuzzy.rb +17 -0
- data/lib/gamefic/scanner/fuzzy_nesting.rb +14 -0
- data/lib/gamefic/scanner/nesting.rb +39 -0
- data/lib/gamefic/scanner/result.rb +50 -0
- data/lib/gamefic/scanner/strict.rb +31 -0
- data/lib/gamefic/scanner.rb +33 -111
- data/lib/gamefic/scope/descendants.rb +16 -0
- data/lib/gamefic/scope/family.rb +31 -8
- data/lib/gamefic/scope.rb +1 -0
- data/lib/gamefic/scriptable/actions.rb +4 -23
- data/lib/gamefic/scriptable/entities.rb +4 -1
- data/lib/gamefic/scriptable/plot_proxies.rb +16 -0
- data/lib/gamefic/scriptable/proxies.rb +31 -0
- data/lib/gamefic/scriptable/queries.rb +15 -7
- data/lib/gamefic/scriptable/scenes.rb +7 -1
- data/lib/gamefic/scriptable.rb +67 -15
- data/lib/gamefic/stage.rb +2 -2
- data/lib/gamefic/subplot.rb +27 -1
- data/lib/gamefic/version.rb +1 -1
- data/lib/gamefic.rb +1 -1
- metadata +12 -4
- data/lib/gamefic/composer.rb +0 -70
- data/lib/gamefic/scriptable/proxy.rb +0 -69
@@ -0,0 +1,31 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Gamefic
|
4
|
+
module Scriptable
|
5
|
+
# Methods for referencing entities from proxies.
|
6
|
+
#
|
7
|
+
module Proxies
|
8
|
+
# Convert a proxy into its referenced entity.
|
9
|
+
#
|
10
|
+
# This method can receive any kind of object. If it's a proxy, its entity
|
11
|
+
# will be returned. If it's an array, each of its elements will be
|
12
|
+
# unproxied. If it's a hash, each of its values will be unproxied. Any
|
13
|
+
# other object will be returned unchanged.
|
14
|
+
#
|
15
|
+
# @param object [Object]
|
16
|
+
# @return [Object]
|
17
|
+
def unproxy object
|
18
|
+
case object
|
19
|
+
when Proxy
|
20
|
+
object.fetch self
|
21
|
+
when Array
|
22
|
+
object.map { |obj| unproxy obj }
|
23
|
+
when Hash
|
24
|
+
object.transform_values { |val| unproxy val }
|
25
|
+
else
|
26
|
+
object
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
@@ -5,14 +5,14 @@ module Gamefic
|
|
5
5
|
# Scriptable methods related to creating action queries.
|
6
6
|
#
|
7
7
|
module Queries
|
8
|
-
include
|
8
|
+
include Proxies
|
9
9
|
|
10
10
|
# Define a query that searches the entire plot's entities.
|
11
11
|
#
|
12
12
|
# @param args [Array<Object>] Query arguments
|
13
13
|
# @return [Query::General]
|
14
14
|
def anywhere *args, ambiguous: false
|
15
|
-
Query::General.new -> { entities }, *
|
15
|
+
Query::General.new -> { entities }, *args, ambiguous: ambiguous
|
16
16
|
end
|
17
17
|
|
18
18
|
# Define a query that searches an actor's family of entities. The
|
@@ -22,7 +22,7 @@ module Gamefic
|
|
22
22
|
# @param args [Array<Object>] Query arguments
|
23
23
|
# @return [Query::Scoped]
|
24
24
|
def available *args, ambiguous: false
|
25
|
-
Query::Scoped.new Scope::Family, *
|
25
|
+
Query::Scoped.new Scope::Family, *args, ambiguous: ambiguous
|
26
26
|
end
|
27
27
|
alias family available
|
28
28
|
|
@@ -31,7 +31,7 @@ module Gamefic
|
|
31
31
|
# @param args [Array<Object>] Query arguments
|
32
32
|
# @return [Query::Scoped]
|
33
33
|
def parent *args, ambiguous: false
|
34
|
-
Query::Scoped.new Scope::Parent, *
|
34
|
+
Query::Scoped.new Scope::Parent, *args, ambiguous: ambiguous
|
35
35
|
end
|
36
36
|
|
37
37
|
# Define a query that searches an actor's children.
|
@@ -39,7 +39,15 @@ module Gamefic
|
|
39
39
|
# @param args [Array<Object>] Query arguments
|
40
40
|
# @return [Query::Scoped]
|
41
41
|
def children *args, ambiguous: false
|
42
|
-
Query::Scoped.new Scope::Children, *
|
42
|
+
Query::Scoped.new Scope::Children, *args, ambiguous: ambiguous
|
43
|
+
end
|
44
|
+
|
45
|
+
# Define a query that searches an actor's descendants.
|
46
|
+
#
|
47
|
+
# @param args [Array<Object>] Query arguments
|
48
|
+
# @return [Query::Scoped]
|
49
|
+
def descendants *args, ambiguous: false
|
50
|
+
Query::Scoped.new Scope::Descendants, *args, ambiguous: ambiguous
|
43
51
|
end
|
44
52
|
|
45
53
|
# Define a query that searches an actor's siblings.
|
@@ -47,7 +55,7 @@ module Gamefic
|
|
47
55
|
# @param args [Array<Object>] Query arguments
|
48
56
|
# @return [Query::Scoped]
|
49
57
|
def siblings *args, ambiguous: false
|
50
|
-
Query::Scoped.new Scope::Siblings, *
|
58
|
+
Query::Scoped.new Scope::Siblings, *args, ambiguous: ambiguous
|
51
59
|
end
|
52
60
|
|
53
61
|
# Define a query that returns the actor itself.
|
@@ -55,7 +63,7 @@ module Gamefic
|
|
55
63
|
# @param args [Array<Object>] Query arguments
|
56
64
|
# @return [Query::Scoped]
|
57
65
|
def myself *args, ambiguous: false
|
58
|
-
Query::Scoped.new Scope::Myself, *
|
66
|
+
Query::Scoped.new Scope::Myself, *args, ambiguous: ambiguous
|
59
67
|
end
|
60
68
|
|
61
69
|
# Define a query that performs a plaintext search. It can take a String
|
@@ -36,7 +36,6 @@ module Gamefic
|
|
36
36
|
rulebook.scenes.add klass.new(name, self, on_start: on_start, on_finish: on_finish, &blk)
|
37
37
|
name
|
38
38
|
end
|
39
|
-
alias scene block
|
40
39
|
|
41
40
|
def preface name, klass = Scene::Activity, &start
|
42
41
|
rulebook.scenes.add klass.new(name, self, on_start: start)
|
@@ -160,9 +159,16 @@ module Gamefic
|
|
160
159
|
on_start: start
|
161
160
|
end
|
162
161
|
|
162
|
+
# @return [Array<Symbol>]
|
163
163
|
def scenes
|
164
164
|
rulebook.scenes.names
|
165
165
|
end
|
166
|
+
|
167
|
+
# @param name [Symbol]
|
168
|
+
# @return [Scene::Default, nil]
|
169
|
+
def scene(name)
|
170
|
+
rulebook.scenes[name]
|
171
|
+
end
|
166
172
|
end
|
167
173
|
end
|
168
174
|
end
|
data/lib/gamefic/scriptable.rb
CHANGED
@@ -23,14 +23,14 @@ module Gamefic
|
|
23
23
|
# end
|
24
24
|
#
|
25
25
|
module Scriptable
|
26
|
-
autoload :Actions,
|
27
|
-
autoload :Entities,
|
28
|
-
autoload :Events,
|
29
|
-
autoload :Queries,
|
30
|
-
autoload :
|
31
|
-
autoload :Scenes,
|
32
|
-
|
33
|
-
|
26
|
+
autoload :Actions, 'gamefic/scriptable/actions'
|
27
|
+
autoload :Entities, 'gamefic/scriptable/entities'
|
28
|
+
autoload :Events, 'gamefic/scriptable/events'
|
29
|
+
autoload :Queries, 'gamefic/scriptable/queries'
|
30
|
+
autoload :Proxies, 'gamefic/scriptable/proxies'
|
31
|
+
autoload :Scenes, 'gamefic/scriptable/scenes'
|
32
|
+
autoload :PlotProxies, 'gamefic/scriptable/plot_proxies'
|
33
|
+
|
34
34
|
include Queries
|
35
35
|
# @!parse
|
36
36
|
# include Scriptable::Actions
|
@@ -101,10 +101,10 @@ module Gamefic
|
|
101
101
|
# make_seed Gamefic::Entity, name: 'thing'
|
102
102
|
#
|
103
103
|
# @param klass [Class<Gamefic::Entity>]
|
104
|
+
# @return [void]
|
104
105
|
def make_seed klass, **opts
|
105
|
-
@count ||= 0
|
106
106
|
seed { make(klass, **opts) }
|
107
|
-
|
107
|
+
nil
|
108
108
|
end
|
109
109
|
|
110
110
|
# Seed an entity with an attribute method.
|
@@ -119,15 +119,67 @@ module Gamefic
|
|
119
119
|
#
|
120
120
|
# @param name [Symbol] The attribute name
|
121
121
|
# @param klass [Class<Gamefic::Entity>]
|
122
|
+
# @return [Proxy]
|
122
123
|
def attr_seed name, klass, **opts
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
124
|
+
ivname = "@#{name}"
|
125
|
+
define_method(name) do
|
126
|
+
return instance_variable_get(ivname) if instance_variable_defined?(ivname)
|
127
|
+
|
128
|
+
instance_variable_set(ivname, make(klass, **opts))
|
129
|
+
end
|
130
|
+
seed { send name }
|
131
|
+
Proxy.new(:attr, name)
|
132
|
+
end
|
133
|
+
|
134
|
+
# @param symbol [Symbol]
|
135
|
+
# @return [Proxy]
|
136
|
+
def proxy symbol
|
137
|
+
Logging.logger.warn "#proxy is deprecated. Use lazy_attr, lazy_ivar, or lazy_pick instead"
|
138
|
+
if symbol.to_s.start_with?('@')
|
139
|
+
lazy_ivar(symbol)
|
140
|
+
else
|
141
|
+
lazy_attr(symbol)
|
127
142
|
end
|
128
|
-
Proxy::Agent.new(@count.tap { @count += 1 })
|
129
143
|
end
|
130
144
|
|
145
|
+
# Lazy reference an entity by its instance variable.
|
146
|
+
#
|
147
|
+
# @example
|
148
|
+
# lazy_ivar(:@variable)
|
149
|
+
#
|
150
|
+
# @param key [Symbol]
|
151
|
+
# @return [Proxy]
|
152
|
+
def lazy_ivar key
|
153
|
+
Proxy.new(:ivar, key)
|
154
|
+
end
|
155
|
+
alias _ivar lazy_ivar
|
156
|
+
|
157
|
+
# Lazy reference an entity by its attribute or method.
|
158
|
+
#
|
159
|
+
# @example
|
160
|
+
# lazy_attr(:method)
|
161
|
+
#
|
162
|
+
# @param key [Symbol]
|
163
|
+
# @return [Proxy]
|
164
|
+
def lazy_attr key
|
165
|
+
Proxy.new(:attr, key)
|
166
|
+
end
|
167
|
+
alias _attr lazy_attr
|
168
|
+
|
169
|
+
# Lazy reference an entity by its description.
|
170
|
+
#
|
171
|
+
# @example
|
172
|
+
# lazy_pick('the red box')
|
173
|
+
#
|
174
|
+
# @raise [RuntimeError] if a unique match could not be found.
|
175
|
+
#
|
176
|
+
# @param description [String]
|
177
|
+
# @return [Proxy]
|
178
|
+
def lazy_pick description
|
179
|
+
Proxy.new(:pick, description)
|
180
|
+
end
|
181
|
+
alias _pick lazy_pick
|
182
|
+
|
131
183
|
if RUBY_ENGINE == 'opal'
|
132
184
|
# :nocov:
|
133
185
|
def method_missing method, *args, &block
|
data/lib/gamefic/stage.rb
CHANGED
@@ -14,7 +14,7 @@ module Gamefic
|
|
14
14
|
|
15
15
|
OVERWRITEABLE_CLASSES = [String, Numeric, Symbol].freeze
|
16
16
|
|
17
|
-
SWAPPABLE_VALUES = [true, false
|
17
|
+
SWAPPABLE_VALUES = [true, false].freeze
|
18
18
|
|
19
19
|
class << self
|
20
20
|
private
|
@@ -37,7 +37,7 @@ module Gamefic
|
|
37
37
|
end
|
38
38
|
|
39
39
|
def overwriteable? cval, nval
|
40
|
-
return true if swappable?(cval, nval)
|
40
|
+
return true if cval.nil? || swappable?(cval, nval)
|
41
41
|
|
42
42
|
allowed = OVERWRITEABLE_CLASSES.find { |klass| cval.is_a?(klass) }
|
43
43
|
allowed && cval.is_a?(allowed)
|
data/lib/gamefic/subplot.rb
CHANGED
@@ -7,6 +7,8 @@ module Gamefic
|
|
7
7
|
# started and concluded at any time during the parent plot's runtime.
|
8
8
|
#
|
9
9
|
class Subplot < Narrative
|
10
|
+
extend Scriptable::PlotProxies
|
11
|
+
|
10
12
|
# @return [Hash]
|
11
13
|
attr_reader :config
|
12
14
|
|
@@ -22,7 +24,20 @@ module Gamefic
|
|
22
24
|
configure
|
23
25
|
@config.freeze
|
24
26
|
super()
|
25
|
-
|
27
|
+
@concluded = false
|
28
|
+
[introduce].flatten.each { |plyr| self.introduce plyr }
|
29
|
+
end
|
30
|
+
|
31
|
+
def self.persist!
|
32
|
+
@persistent = true
|
33
|
+
end
|
34
|
+
|
35
|
+
def self.persistent?
|
36
|
+
@persistent ||= false
|
37
|
+
end
|
38
|
+
|
39
|
+
def persistent?
|
40
|
+
self.class.persistent?
|
26
41
|
end
|
27
42
|
|
28
43
|
def included_blocks
|
@@ -41,6 +56,7 @@ module Gamefic
|
|
41
56
|
uncast plyr
|
42
57
|
end
|
43
58
|
entities.each { |ent| destroy ent }
|
59
|
+
@concluded = true
|
44
60
|
end
|
45
61
|
|
46
62
|
# Make an entity that persists in the subplot's parent plot.
|
@@ -69,6 +85,16 @@ module Gamefic
|
|
69
85
|
#
|
70
86
|
def configure; end
|
71
87
|
|
88
|
+
def concluding?
|
89
|
+
return super unless persistent?
|
90
|
+
|
91
|
+
@concluded
|
92
|
+
end
|
93
|
+
|
94
|
+
def introduce player
|
95
|
+
@concluded ? player : super
|
96
|
+
end
|
97
|
+
|
72
98
|
def inspect
|
73
99
|
"#<#{self.class}>"
|
74
100
|
end
|
data/lib/gamefic/version.rb
CHANGED
data/lib/gamefic.rb
CHANGED
@@ -17,6 +17,7 @@ require 'gamefic/command'
|
|
17
17
|
require 'gamefic/action'
|
18
18
|
require 'gamefic/props'
|
19
19
|
require 'gamefic/scene'
|
20
|
+
require 'gamefic/proxy'
|
20
21
|
require 'gamefic/scriptable'
|
21
22
|
require 'gamefic/block'
|
22
23
|
require 'gamefic/stage'
|
@@ -30,7 +31,6 @@ require 'gamefic/node'
|
|
30
31
|
require 'gamefic/describable'
|
31
32
|
require 'gamefic/messenger'
|
32
33
|
require 'gamefic/entity'
|
33
|
-
require 'gamefic/composer'
|
34
34
|
require 'gamefic/dispatcher'
|
35
35
|
require 'gamefic/active'
|
36
36
|
require 'gamefic/active/cue'
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: gamefic
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 3.
|
4
|
+
version: 3.5.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Fred Snyder
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2024-
|
11
|
+
date: 2024-10-05 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: opal
|
@@ -138,7 +138,6 @@ files:
|
|
138
138
|
- lib/gamefic/callback.rb
|
139
139
|
- lib/gamefic/chapter.rb
|
140
140
|
- lib/gamefic/command.rb
|
141
|
-
- lib/gamefic/composer.rb
|
142
141
|
- lib/gamefic/core_ext/array.rb
|
143
142
|
- lib/gamefic/core_ext/string.rb
|
144
143
|
- lib/gamefic/describable.rb
|
@@ -156,6 +155,7 @@ files:
|
|
156
155
|
- lib/gamefic/props/output.rb
|
157
156
|
- lib/gamefic/props/pause.rb
|
158
157
|
- lib/gamefic/props/yes_or_no.rb
|
158
|
+
- lib/gamefic/proxy.rb
|
159
159
|
- lib/gamefic/query.rb
|
160
160
|
- lib/gamefic/query/base.rb
|
161
161
|
- lib/gamefic/query/general.rb
|
@@ -169,6 +169,12 @@ files:
|
|
169
169
|
- lib/gamefic/rulebook/hooks.rb
|
170
170
|
- lib/gamefic/rulebook/scenes.rb
|
171
171
|
- lib/gamefic/scanner.rb
|
172
|
+
- lib/gamefic/scanner/base.rb
|
173
|
+
- lib/gamefic/scanner/fuzzy.rb
|
174
|
+
- lib/gamefic/scanner/fuzzy_nesting.rb
|
175
|
+
- lib/gamefic/scanner/nesting.rb
|
176
|
+
- lib/gamefic/scanner/result.rb
|
177
|
+
- lib/gamefic/scanner/strict.rb
|
172
178
|
- lib/gamefic/scene.rb
|
173
179
|
- lib/gamefic/scene/activity.rb
|
174
180
|
- lib/gamefic/scene/conclusion.rb
|
@@ -179,6 +185,7 @@ files:
|
|
179
185
|
- lib/gamefic/scope.rb
|
180
186
|
- lib/gamefic/scope/base.rb
|
181
187
|
- lib/gamefic/scope/children.rb
|
188
|
+
- lib/gamefic/scope/descendants.rb
|
182
189
|
- lib/gamefic/scope/family.rb
|
183
190
|
- lib/gamefic/scope/myself.rb
|
184
191
|
- lib/gamefic/scope/parent.rb
|
@@ -187,7 +194,8 @@ files:
|
|
187
194
|
- lib/gamefic/scriptable/actions.rb
|
188
195
|
- lib/gamefic/scriptable/entities.rb
|
189
196
|
- lib/gamefic/scriptable/events.rb
|
190
|
-
- lib/gamefic/scriptable/
|
197
|
+
- lib/gamefic/scriptable/plot_proxies.rb
|
198
|
+
- lib/gamefic/scriptable/proxies.rb
|
191
199
|
- lib/gamefic/scriptable/queries.rb
|
192
200
|
- lib/gamefic/scriptable/scenes.rb
|
193
201
|
- lib/gamefic/snapshot.rb
|
data/lib/gamefic/composer.rb
DELETED
@@ -1,70 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module Gamefic
|
4
|
-
# A function module for creating commands from expressions.
|
5
|
-
#
|
6
|
-
module Composer
|
7
|
-
# Create a command from the first expression that matches a response.
|
8
|
-
#
|
9
|
-
# @param actor [Actor]
|
10
|
-
# @param expressions [Array<Expression>]
|
11
|
-
# @return [Command]
|
12
|
-
def self.compose actor, expressions
|
13
|
-
%i[strict fuzzy].each do |method|
|
14
|
-
result = match_expressions_to_response actor, expressions, method
|
15
|
-
return result if result
|
16
|
-
end
|
17
|
-
Command.new(nil, [])
|
18
|
-
end
|
19
|
-
|
20
|
-
class << self
|
21
|
-
private
|
22
|
-
|
23
|
-
def match_expressions_to_response actor, expressions, method
|
24
|
-
expressions.each do |expression|
|
25
|
-
result = match_response_arguments actor, expression, method
|
26
|
-
return result if result
|
27
|
-
end
|
28
|
-
nil
|
29
|
-
end
|
30
|
-
|
31
|
-
def match_response_arguments actor, expression, method
|
32
|
-
actor.epic.responses_for(expression.verb).each do |response|
|
33
|
-
next unless response.queries.length >= expression.tokens.length
|
34
|
-
|
35
|
-
result = match_query_arguments(actor, expression, response, method)
|
36
|
-
return result if result
|
37
|
-
end
|
38
|
-
nil
|
39
|
-
end
|
40
|
-
|
41
|
-
def match_query_arguments actor, expression, response, method
|
42
|
-
remainder = response.verb ? '' : expression.verb.to_s
|
43
|
-
arguments = []
|
44
|
-
response.queries.each_with_index do |query, idx|
|
45
|
-
result = Scanner.send(method, query.select(actor), "#{remainder} #{expression.tokens[idx]}".strip)
|
46
|
-
break unless valid_result_from_query?(result, query)
|
47
|
-
|
48
|
-
if query.ambiguous?
|
49
|
-
arguments.push result.matched
|
50
|
-
else
|
51
|
-
arguments.push result.matched.first
|
52
|
-
end
|
53
|
-
remainder = result.remainder
|
54
|
-
end
|
55
|
-
|
56
|
-
return nil if arguments.length != response.queries.length || remainder != ''
|
57
|
-
|
58
|
-
Command.new(response.verb, arguments)
|
59
|
-
end
|
60
|
-
|
61
|
-
# @param result [Scanner::Result]
|
62
|
-
# @param query [Query::Base]
|
63
|
-
def valid_result_from_query? result, query
|
64
|
-
return false if result.matched.empty?
|
65
|
-
|
66
|
-
result.matched.length == 1 || query.ambiguous?
|
67
|
-
end
|
68
|
-
end
|
69
|
-
end
|
70
|
-
end
|
@@ -1,69 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module Gamefic
|
4
|
-
module Scriptable
|
5
|
-
# Functions that provide proxies for referencing a narrative's entities
|
6
|
-
# from class-level scripts.
|
7
|
-
#
|
8
|
-
module Proxy
|
9
|
-
# The object that fetches a proxied entity.
|
10
|
-
#
|
11
|
-
class Agent
|
12
|
-
attr_reader :symbol
|
13
|
-
|
14
|
-
# @param symbol [Symbol, Integer]
|
15
|
-
def initialize symbol
|
16
|
-
@symbol = symbol
|
17
|
-
end
|
18
|
-
|
19
|
-
def fetch container
|
20
|
-
result = safe_fetch(container)
|
21
|
-
raise ArgumentError, "Unable to fetch entity from proxy agent symbol `#{symbol}`" unless result
|
22
|
-
|
23
|
-
result
|
24
|
-
end
|
25
|
-
|
26
|
-
private
|
27
|
-
|
28
|
-
def safe_fetch container
|
29
|
-
if symbol.to_s =~ /^\d+$/
|
30
|
-
Stage.run(container, symbol) { |sym| entities[sym] }
|
31
|
-
elsif symbol.to_s.start_with?('@')
|
32
|
-
Stage.run(container, symbol) { |sym| instance_variable_get(sym) }
|
33
|
-
else
|
34
|
-
Stage.run(container, symbol) { |sym| send(sym) }
|
35
|
-
end
|
36
|
-
rescue NoMethodError
|
37
|
-
nil
|
38
|
-
end
|
39
|
-
end
|
40
|
-
|
41
|
-
# Proxy a method or instance variable.
|
42
|
-
#
|
43
|
-
# @example
|
44
|
-
# proxy(:method_name)
|
45
|
-
# proxy(:@instance_variable_name)
|
46
|
-
#
|
47
|
-
# @param symbol [Symbol]
|
48
|
-
# @return [Agent]
|
49
|
-
def proxy symbol
|
50
|
-
Agent.new(symbol)
|
51
|
-
end
|
52
|
-
|
53
|
-
# @param object [Object]
|
54
|
-
# @return [Object]
|
55
|
-
def unproxy object
|
56
|
-
case object
|
57
|
-
when Agent
|
58
|
-
object.fetch self
|
59
|
-
when Array
|
60
|
-
object.map { |obj| unproxy obj }
|
61
|
-
when Hash
|
62
|
-
object.transform_values { |val| unproxy val }
|
63
|
-
else
|
64
|
-
object
|
65
|
-
end
|
66
|
-
end
|
67
|
-
end
|
68
|
-
end
|
69
|
-
end
|