volt 0.9.3.pre2 → 0.9.3.pre3
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 +12 -0
- data/app/volt/tasks/query_tasks.rb +0 -7
- data/app/volt/tasks/store_tasks.rb +0 -6
- data/docs/UPGRADE_GUIDE.md +2 -0
- data/lib/volt/cli/asset_compile.rb +2 -2
- data/lib/volt/cli/console.rb +21 -0
- data/lib/volt/config.rb +0 -10
- data/lib/volt/controllers/collection_helpers.rb +18 -0
- data/lib/volt/controllers/model_controller.rb +2 -12
- data/lib/volt/extra_core/object.rb +19 -0
- data/lib/volt/models.rb +14 -9
- data/lib/volt/models/array_model.rb +62 -22
- data/lib/volt/models/associations.rb +16 -1
- data/lib/volt/models/model.rb +27 -15
- data/lib/volt/models/model_helpers/model_helpers.rb +29 -0
- data/lib/volt/models/permissions.rb +15 -4
- data/lib/volt/models/persistors/array_store.rb +40 -0
- data/lib/volt/models/persistors/model_store.rb +2 -2
- data/lib/volt/models/persistors/query/query_listener.rb +3 -1
- data/lib/volt/models/persistors/store.rb +2 -1
- data/lib/volt/models/root_models/root_models.rb +31 -0
- data/lib/volt/models/root_models/store_root.rb +36 -0
- data/lib/volt/models/validators/unique_validator.rb +1 -1
- data/lib/volt/page/bindings/each_binding.rb +56 -47
- data/lib/volt/page/page.rb +5 -5
- data/lib/volt/reactive/reactive_array.rb +9 -6
- data/lib/volt/server.rb +2 -2
- data/lib/volt/server/component_templates.rb +7 -4
- data/lib/volt/server/message_bus/message_encoder.rb +9 -1
- data/lib/volt/server/rack/component_code.rb +8 -1
- data/lib/volt/server/rack/index_files.rb +5 -2
- data/lib/volt/tasks/{task_handler.rb → task.rb} +6 -6
- data/lib/volt/utils/promise.rb +429 -0
- data/lib/volt/utils/promise_extensions.rb +79 -0
- data/lib/volt/version.rb +1 -1
- data/lib/volt/volt/app.rb +5 -2
- data/lib/volt/volt/server_setup/app.rb +28 -7
- data/spec/apps/kitchen_sink/app/main/controllers/server/simple_http_controller.rb +1 -1
- data/spec/apps/kitchen_sink/app/main/views/main/store.html +3 -0
- data/spec/extra_core/object_spec.rb +13 -0
- data/spec/integration/store_spec.rb +10 -0
- data/spec/models/associations_spec.rb +48 -26
- data/spec/models/model_spec.rb +23 -7
- data/spec/models/persistors/store_spec.rb +28 -0
- data/spec/models/validators/unique_validator_spec.rb +1 -1
- data/spec/spec_helper.rb +4 -1
- data/spec/utils/promise_extensions_spec.rb +42 -0
- data/templates/component/config/initializers/boot.rb +10 -0
- data/templates/{project/app → component/config/initializers/client}/.empty_directory +0 -0
- data/templates/component/config/initializers/server/.empty_directory +0 -0
- data/templates/newgem/app/newgem/config/initializers/client/.empty_directory +0 -0
- data/templates/newgem/app/newgem/config/initializers/server/.empty_directory +0 -0
- data/templates/project/Gemfile.tt +6 -2
- data/templates/project/app/main/config/initializers/boot.rb +10 -0
- data/templates/project/app/main/config/initializers/client/.empty_directory +0 -0
- data/templates/project/app/main/config/initializers/server/.empty_directory +0 -0
- data/templates/project/config/app.rb.tt +3 -0
- data/templates/project/config/initializers/client/.empty_directory +0 -0
- data/templates/project/config/initializers/server/.empty_directory +0 -0
- metadata +22 -5
- data/lib/volt/utils/promise_patch.rb +0 -70
data/lib/volt/server.rb
CHANGED
@@ -10,7 +10,7 @@ require 'sprockets-sass'
|
|
10
10
|
|
11
11
|
require 'volt'
|
12
12
|
require 'volt/tasks/dispatcher'
|
13
|
-
require 'volt/tasks/
|
13
|
+
require 'volt/tasks/task'
|
14
14
|
require 'volt/server/component_handler'
|
15
15
|
require 'volt/server/rack/component_paths'
|
16
16
|
require 'volt/server/rack/index_files'
|
@@ -133,7 +133,7 @@ module Volt
|
|
133
133
|
|
134
134
|
# Serve the main html files from public, also figure out
|
135
135
|
# which JS/CSS files to serve.
|
136
|
-
@rack_app.use IndexFiles, @volt_app.component_paths, opal_files
|
136
|
+
@rack_app.use IndexFiles, @volt_app, @volt_app.component_paths, opal_files
|
137
137
|
|
138
138
|
@rack_app.use HttpResource, @volt_app, @volt_app.router
|
139
139
|
|
@@ -1,5 +1,5 @@
|
|
1
1
|
require 'volt/server/html_parser/view_parser'
|
2
|
-
require 'volt/tasks/
|
2
|
+
require 'volt/tasks/task'
|
3
3
|
|
4
4
|
# Initialize with the path to a component and returns all the front-end
|
5
5
|
# setup code (for controllers, models, views, and routes)
|
@@ -91,7 +91,7 @@ module Volt
|
|
91
91
|
|
92
92
|
file_contents = File.read(view_path)
|
93
93
|
|
94
|
-
template_calls = []
|
94
|
+
# template_calls = []
|
95
95
|
|
96
96
|
# Process template if we have a handler for this file type
|
97
97
|
if handler = ComponentTemplates.handler_for_extension(format)
|
@@ -112,7 +112,7 @@ module Volt
|
|
112
112
|
binding_code = "{#{binding_code.join(', ')}}"
|
113
113
|
|
114
114
|
code << "#{page_reference}.add_template(#{name.inspect}, #{template['html'].inspect}, #{binding_code})\n"
|
115
|
-
template_calls << "template(#{name.inspect}, #{template['html'].inspect}, #{binding_code})"
|
115
|
+
# template_calls << "template(#{name.inspect}, #{template['html'].inspect}, #{binding_code})"
|
116
116
|
end
|
117
117
|
end
|
118
118
|
|
@@ -200,7 +200,10 @@ module Volt
|
|
200
200
|
end
|
201
201
|
|
202
202
|
def generate_initializers_code
|
203
|
-
"\nrequire_tree '#{@component_path}/config/initializers/'\n"
|
203
|
+
code = "\nrequire_tree '#{@component_path}/config/initializers/'\n"
|
204
|
+
code << "require_tree '#{@component_path}/config/initializers/client'\n"
|
205
|
+
|
206
|
+
code
|
204
207
|
end
|
205
208
|
|
206
209
|
end
|
@@ -5,8 +5,16 @@ module Volt
|
|
5
5
|
class MessageEncoder
|
6
6
|
attr_reader :encrypted
|
7
7
|
def initialize
|
8
|
+
# rbnacl is not supported on windows.
|
9
|
+
windows = Gem.win_platform?
|
10
|
+
|
11
|
+
if windows
|
12
|
+
Volt.logger.warn('Currently Message Bus encryption is not supported on windows.')
|
13
|
+
end
|
14
|
+
|
8
15
|
# Message bus is encrypted by default
|
9
|
-
|
16
|
+
disable = Volt.config.message_bus.try(:disable_encryption)
|
17
|
+
@encrypted = !windows && (disable != true)
|
10
18
|
|
11
19
|
if @encrypted
|
12
20
|
# Setup a RbNaCl simple box for handling encryption
|
@@ -27,7 +27,14 @@ module Volt
|
|
27
27
|
end
|
28
28
|
|
29
29
|
def generate_config_code
|
30
|
-
|
30
|
+
# Setup Volt.config on the client
|
31
|
+
code = "\nVolt.setup_client_config(#{Volt.config.public.to_h.inspect})\n"
|
32
|
+
|
33
|
+
# Include the root initializers
|
34
|
+
code << "require_tree '#{Volt.root}/config/initializers'\n"
|
35
|
+
code << "require_tree '#{Volt.root}/config/initializers/client'\n"
|
36
|
+
|
37
|
+
code
|
31
38
|
end
|
32
39
|
end
|
33
40
|
end
|
@@ -4,12 +4,15 @@ require 'volt/router/routes'
|
|
4
4
|
# Serves the main pages
|
5
5
|
module Volt
|
6
6
|
class IndexFiles
|
7
|
-
def initialize(app, component_paths, opal_files)
|
7
|
+
def initialize(app, volt_app, component_paths, opal_files)
|
8
8
|
@app = app
|
9
|
+
@volt_app = volt_app
|
9
10
|
@component_paths = component_paths
|
10
11
|
@opal_files = opal_files
|
11
12
|
|
12
|
-
@@router
|
13
|
+
@@router = volt_app.router
|
14
|
+
|
15
|
+
@@router.define do
|
13
16
|
# Load routes for each component
|
14
17
|
component_paths.components.values.flatten.uniq.each do |component_path|
|
15
18
|
routes_path = "#{component_path}/config/routes.rb"
|
@@ -1,3 +1,5 @@
|
|
1
|
+
require 'volt/controllers/collection_helpers'
|
2
|
+
|
1
3
|
module Volt
|
2
4
|
class Task
|
3
5
|
if RUBY_PLATFORM == 'opal'
|
@@ -14,8 +16,11 @@ module Volt
|
|
14
16
|
$page.tasks.call(self.name, name, meta_data, *args, &block)
|
15
17
|
end
|
16
18
|
else
|
19
|
+
include CollectionHelpers
|
20
|
+
|
17
21
|
def initialize(volt_app, channel = nil, dispatcher = nil)
|
18
|
-
@volt_app
|
22
|
+
@volt_app = volt_app
|
23
|
+
@page = volt_app.page
|
19
24
|
@channel = channel
|
20
25
|
@dispatcher = dispatcher
|
21
26
|
end
|
@@ -39,11 +44,6 @@ module Volt
|
|
39
44
|
new(Volt.current_app, nil, nil).send(name, *args, &block)
|
40
45
|
end.resolve(nil)
|
41
46
|
end
|
42
|
-
|
43
|
-
# Provide access to the store collection
|
44
|
-
def store
|
45
|
-
$page.store
|
46
|
-
end
|
47
47
|
end
|
48
48
|
end
|
49
49
|
end
|
@@ -0,0 +1,429 @@
|
|
1
|
+
# A copy of the opal 0.8 promise library. The one in 0.7.x has some bugs.
|
2
|
+
|
3
|
+
# {Promise} is used to help structure asynchronous code.
|
4
|
+
#
|
5
|
+
# It is available in the Opal standard library, and can be required in any Opal
|
6
|
+
# application:
|
7
|
+
#
|
8
|
+
# require 'promise'
|
9
|
+
#
|
10
|
+
# ## Basic Usage
|
11
|
+
#
|
12
|
+
# Promises are created and returned as objects with the assumption that they
|
13
|
+
# will eventually be resolved or rejected, but never both. A {Promise} has
|
14
|
+
# a {#then} and {#fail} method (or one of their aliases) that can be used to
|
15
|
+
# register a block that gets called once resolved or rejected.
|
16
|
+
#
|
17
|
+
# promise = Promise.new
|
18
|
+
#
|
19
|
+
# promise.then {
|
20
|
+
# puts "resolved!"
|
21
|
+
# }.fail {
|
22
|
+
# puts "rejected!"
|
23
|
+
# }
|
24
|
+
#
|
25
|
+
# # some time later
|
26
|
+
# promise.resolve
|
27
|
+
#
|
28
|
+
# # => "resolved!"
|
29
|
+
#
|
30
|
+
# It is important to remember that a promise can only be resolved or rejected
|
31
|
+
# once, so the block will only ever be called once (or not at all).
|
32
|
+
#
|
33
|
+
# ## Resolving Promises
|
34
|
+
#
|
35
|
+
# To resolve a promise, means to inform the {Promise} that it has succeeded
|
36
|
+
# or evaluated to a useful value. {#resolve} can be passed a value which is
|
37
|
+
# then passed into the block handler:
|
38
|
+
#
|
39
|
+
# def get_json
|
40
|
+
# promise = Promise.new
|
41
|
+
#
|
42
|
+
# HTTP.get("some_url") do |req|
|
43
|
+
# promise.resolve req.json
|
44
|
+
# end
|
45
|
+
#
|
46
|
+
# promise
|
47
|
+
# end
|
48
|
+
#
|
49
|
+
# get_json.then do |json|
|
50
|
+
# puts "got some JSON from server"
|
51
|
+
# end
|
52
|
+
#
|
53
|
+
# ## Rejecting Promises
|
54
|
+
#
|
55
|
+
# Promises are also designed to handle error cases, or situations where an
|
56
|
+
# outcome is not as expected. Taking the previous example, we can also pass
|
57
|
+
# a value to a {#reject} call, which passes that object to the registered
|
58
|
+
# {#fail} handler:
|
59
|
+
#
|
60
|
+
# def get_json
|
61
|
+
# promise = Promise.new
|
62
|
+
#
|
63
|
+
# HTTP.get("some_url") do |req|
|
64
|
+
# if req.ok?
|
65
|
+
# promise.resolve req.json
|
66
|
+
# else
|
67
|
+
# promise.reject req
|
68
|
+
# end
|
69
|
+
#
|
70
|
+
# promise
|
71
|
+
# end
|
72
|
+
#
|
73
|
+
# get_json.then {
|
74
|
+
# # ...
|
75
|
+
# }.fail { |req|
|
76
|
+
# puts "it went wrong: #{req.message}"
|
77
|
+
# }
|
78
|
+
#
|
79
|
+
# ## Chaining Promises
|
80
|
+
#
|
81
|
+
# Promises become even more useful when chained together. Each {#then} or
|
82
|
+
# {#fail} call returns a new {Promise} which can be used to chain more and more
|
83
|
+
# handlers together.
|
84
|
+
#
|
85
|
+
# promise.then { wait_for_something }.then { do_something_else }
|
86
|
+
#
|
87
|
+
# Rejections are propagated through the entire chain, so a "catch all" handler
|
88
|
+
# can be attached at the end of the tail:
|
89
|
+
#
|
90
|
+
# promise.then { ... }.then { ... }.fail { ... }
|
91
|
+
#
|
92
|
+
# ## Composing Promises
|
93
|
+
#
|
94
|
+
# {Promise.when} can be used to wait for more than one promise to resolve (or
|
95
|
+
# reject). Using the previous example, we could request two different json
|
96
|
+
# requests and wait for both to finish:
|
97
|
+
#
|
98
|
+
# Promise.when(get_json, get_json2).then |first, second|
|
99
|
+
# puts "got two json payloads: #{first}, #{second}"
|
100
|
+
# end
|
101
|
+
#
|
102
|
+
class Promise
|
103
|
+
def self.value(value)
|
104
|
+
new.resolve(value)
|
105
|
+
end
|
106
|
+
|
107
|
+
def self.error(value)
|
108
|
+
new.reject(value)
|
109
|
+
end
|
110
|
+
|
111
|
+
def self.when(*promises)
|
112
|
+
When.new(promises)
|
113
|
+
end
|
114
|
+
|
115
|
+
attr_reader :error, :prev, :next
|
116
|
+
|
117
|
+
def initialize(action = {})
|
118
|
+
@action = action
|
119
|
+
|
120
|
+
@realized = false
|
121
|
+
@exception = false
|
122
|
+
@value = nil
|
123
|
+
@error = nil
|
124
|
+
@delayed = false
|
125
|
+
|
126
|
+
@prev = nil
|
127
|
+
@next = nil
|
128
|
+
end
|
129
|
+
|
130
|
+
def value
|
131
|
+
if Promise === @value
|
132
|
+
@value.value
|
133
|
+
else
|
134
|
+
@value
|
135
|
+
end
|
136
|
+
end
|
137
|
+
|
138
|
+
def act?
|
139
|
+
@action.has_key?(:success) || @action.has_key?(:always)
|
140
|
+
end
|
141
|
+
|
142
|
+
def action
|
143
|
+
@action.keys
|
144
|
+
end
|
145
|
+
|
146
|
+
def exception?
|
147
|
+
@exception
|
148
|
+
end
|
149
|
+
|
150
|
+
def realized?
|
151
|
+
!!@realized
|
152
|
+
end
|
153
|
+
|
154
|
+
def resolved?
|
155
|
+
@realized == :resolve
|
156
|
+
end
|
157
|
+
|
158
|
+
def rejected?
|
159
|
+
@realized == :reject
|
160
|
+
end
|
161
|
+
|
162
|
+
def ^(promise)
|
163
|
+
promise << self
|
164
|
+
self >> promise
|
165
|
+
|
166
|
+
promise
|
167
|
+
end
|
168
|
+
|
169
|
+
def <<(promise)
|
170
|
+
@prev = promise
|
171
|
+
|
172
|
+
self
|
173
|
+
end
|
174
|
+
|
175
|
+
def >>(promise)
|
176
|
+
@next = promise
|
177
|
+
|
178
|
+
if exception?
|
179
|
+
promise.reject(@delayed[0])
|
180
|
+
elsif resolved?
|
181
|
+
promise.resolve(@delayed ? @delayed[0] : value)
|
182
|
+
elsif rejected?
|
183
|
+
if !@action.has_key?(:failure) || Promise === (@delayed ? @delayed[0] : @error)
|
184
|
+
promise.reject(@delayed ? @delayed[0] : error)
|
185
|
+
elsif promise.action.include?(:always)
|
186
|
+
promise.reject(@delayed ? @delayed[0] : error)
|
187
|
+
end
|
188
|
+
end
|
189
|
+
|
190
|
+
self
|
191
|
+
end
|
192
|
+
|
193
|
+
def resolve(value = nil)
|
194
|
+
if realized?
|
195
|
+
raise ArgumentError, 'the promise has already been realized'
|
196
|
+
end
|
197
|
+
|
198
|
+
if Promise === value
|
199
|
+
return (value << @prev) ^ self
|
200
|
+
end
|
201
|
+
|
202
|
+
begin
|
203
|
+
if block = @action[:success] || @action[:always]
|
204
|
+
value = block.call(value)
|
205
|
+
end
|
206
|
+
|
207
|
+
resolve!(value)
|
208
|
+
rescue Exception => e
|
209
|
+
exception!(e)
|
210
|
+
end
|
211
|
+
|
212
|
+
self
|
213
|
+
end
|
214
|
+
|
215
|
+
def resolve!(value)
|
216
|
+
@realized = :resolve
|
217
|
+
@value = value
|
218
|
+
|
219
|
+
if @next
|
220
|
+
@next.resolve(value)
|
221
|
+
else
|
222
|
+
@delayed = [value]
|
223
|
+
end
|
224
|
+
end
|
225
|
+
|
226
|
+
def reject(value = nil)
|
227
|
+
if realized?
|
228
|
+
raise ArgumentError, 'the promise has already been realized'
|
229
|
+
end
|
230
|
+
|
231
|
+
if Promise === value
|
232
|
+
return (value << @prev) ^ self
|
233
|
+
end
|
234
|
+
|
235
|
+
begin
|
236
|
+
if block = @action[:failure] || @action[:always]
|
237
|
+
value = block.call(value)
|
238
|
+
end
|
239
|
+
|
240
|
+
if @action.has_key?(:always)
|
241
|
+
resolve!(value)
|
242
|
+
else
|
243
|
+
reject!(value)
|
244
|
+
end
|
245
|
+
rescue Exception => e
|
246
|
+
exception!(e)
|
247
|
+
end
|
248
|
+
|
249
|
+
self
|
250
|
+
end
|
251
|
+
|
252
|
+
def reject!(value)
|
253
|
+
@realized = :reject
|
254
|
+
@error = value
|
255
|
+
|
256
|
+
if @next
|
257
|
+
@next.reject(value)
|
258
|
+
else
|
259
|
+
@delayed = [value]
|
260
|
+
end
|
261
|
+
end
|
262
|
+
|
263
|
+
def exception!(error)
|
264
|
+
@exception = true
|
265
|
+
|
266
|
+
reject!(error)
|
267
|
+
end
|
268
|
+
|
269
|
+
def then(&block)
|
270
|
+
if @next
|
271
|
+
raise ArgumentError, 'a promise has already been chained'
|
272
|
+
end
|
273
|
+
|
274
|
+
self ^ Promise.new(success: block)
|
275
|
+
end
|
276
|
+
|
277
|
+
alias do then
|
278
|
+
|
279
|
+
def fail(&block)
|
280
|
+
if @next
|
281
|
+
raise ArgumentError, 'a promise has already been chained'
|
282
|
+
end
|
283
|
+
|
284
|
+
self ^ Promise.new(failure: block)
|
285
|
+
end
|
286
|
+
|
287
|
+
alias rescue fail
|
288
|
+
alias catch fail
|
289
|
+
|
290
|
+
def always(&block)
|
291
|
+
if @next
|
292
|
+
raise ArgumentError, 'a promise has already been chained'
|
293
|
+
end
|
294
|
+
|
295
|
+
self ^ Promise.new(always: block)
|
296
|
+
end
|
297
|
+
|
298
|
+
alias finally always
|
299
|
+
alias ensure always
|
300
|
+
|
301
|
+
def trace(depth = nil, &block)
|
302
|
+
if @next
|
303
|
+
raise ArgumentError, 'a promise has already been chained'
|
304
|
+
end
|
305
|
+
|
306
|
+
self ^ Trace.new(depth, block)
|
307
|
+
end
|
308
|
+
|
309
|
+
def inspect
|
310
|
+
result = "#<#{self.class}(#{object_id})"
|
311
|
+
|
312
|
+
if @next
|
313
|
+
result += " >> #{@next.inspect}"
|
314
|
+
end
|
315
|
+
|
316
|
+
if realized?
|
317
|
+
result += ": #{(@value || @error).inspect}>"
|
318
|
+
else
|
319
|
+
result += ">"
|
320
|
+
end
|
321
|
+
|
322
|
+
result
|
323
|
+
end
|
324
|
+
|
325
|
+
class Trace < self
|
326
|
+
def self.it(promise)
|
327
|
+
current = []
|
328
|
+
|
329
|
+
if promise.act? || promise.prev.nil?
|
330
|
+
current.push(promise.value)
|
331
|
+
end
|
332
|
+
|
333
|
+
if prev = promise.prev
|
334
|
+
current.concat(it(prev))
|
335
|
+
else
|
336
|
+
current
|
337
|
+
end
|
338
|
+
end
|
339
|
+
|
340
|
+
def initialize(depth, block)
|
341
|
+
@depth = depth
|
342
|
+
|
343
|
+
super success: -> {
|
344
|
+
trace = Trace.it(self).reverse
|
345
|
+
trace.pop
|
346
|
+
|
347
|
+
if depth && depth <= trace.length
|
348
|
+
trace.shift(trace.length - depth)
|
349
|
+
end
|
350
|
+
|
351
|
+
block.call(*trace)
|
352
|
+
}
|
353
|
+
end
|
354
|
+
end
|
355
|
+
|
356
|
+
class When < self
|
357
|
+
def initialize(promises = [])
|
358
|
+
super()
|
359
|
+
|
360
|
+
@wait = []
|
361
|
+
|
362
|
+
promises.each {|promise|
|
363
|
+
wait promise
|
364
|
+
}
|
365
|
+
end
|
366
|
+
|
367
|
+
def each(&block)
|
368
|
+
raise ArgumentError, 'no block given' unless block
|
369
|
+
|
370
|
+
self.then {|values|
|
371
|
+
values.each(&block)
|
372
|
+
}
|
373
|
+
end
|
374
|
+
|
375
|
+
def collect(&block)
|
376
|
+
raise ArgumentError, 'no block given' unless block
|
377
|
+
|
378
|
+
self.then {|values|
|
379
|
+
When.new(values.map(&block))
|
380
|
+
}
|
381
|
+
end
|
382
|
+
|
383
|
+
def inject(*args, &block)
|
384
|
+
self.then {|values|
|
385
|
+
values.reduce(*args, &block)
|
386
|
+
}
|
387
|
+
end
|
388
|
+
|
389
|
+
alias map collect
|
390
|
+
|
391
|
+
alias reduce inject
|
392
|
+
|
393
|
+
def wait(promise)
|
394
|
+
unless Promise === promise
|
395
|
+
promise = Promise.value(promise)
|
396
|
+
end
|
397
|
+
|
398
|
+
if promise.act?
|
399
|
+
promise = promise.then
|
400
|
+
end
|
401
|
+
|
402
|
+
@wait << promise
|
403
|
+
|
404
|
+
promise.always {
|
405
|
+
try if @next
|
406
|
+
}
|
407
|
+
|
408
|
+
self
|
409
|
+
end
|
410
|
+
|
411
|
+
alias and wait
|
412
|
+
|
413
|
+
def >>(*)
|
414
|
+
super.tap {
|
415
|
+
try
|
416
|
+
}
|
417
|
+
end
|
418
|
+
|
419
|
+
def try
|
420
|
+
if @wait.all?(&:realized?)
|
421
|
+
if promise = @wait.find(&:rejected?)
|
422
|
+
reject(promise.error)
|
423
|
+
else
|
424
|
+
resolve(@wait.map(&:value))
|
425
|
+
end
|
426
|
+
end
|
427
|
+
end
|
428
|
+
end
|
429
|
+
end
|