hyper-operation 0.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 +7 -0
- data/.gitignore +49 -0
- data/CODE_OF_CONDUCT.md +49 -0
- data/Gemfile +3 -0
- data/Gemfile.lock +324 -0
- data/LICENSE.txt +21 -0
- data/README.md +708 -0
- data/Rakefile +4 -0
- data/examples/chat-app/.gitignore +21 -0
- data/examples/chat-app/Gemfile +57 -0
- data/examples/chat-app/Gemfile.lock +282 -0
- data/examples/chat-app/README.md +3 -0
- data/examples/chat-app/Rakefile +6 -0
- data/examples/chat-app/app/assets/config/manifest.js +3 -0
- data/examples/chat-app/app/assets/images/.keep +0 -0
- data/examples/chat-app/app/assets/javascripts/application.js +3 -0
- data/examples/chat-app/app/assets/javascripts/cable.js +13 -0
- data/examples/chat-app/app/assets/javascripts/channels/.keep +0 -0
- data/examples/chat-app/app/assets/stylesheets/application.css +15 -0
- data/examples/chat-app/app/channels/application_cable/channel.rb +4 -0
- data/examples/chat-app/app/channels/application_cable/connection.rb +4 -0
- data/examples/chat-app/app/controllers/application_controller.rb +3 -0
- data/examples/chat-app/app/controllers/concerns/.keep +0 -0
- data/examples/chat-app/app/controllers/home_controller.rb +5 -0
- data/examples/chat-app/app/helpers/application_helper.rb +2 -0
- data/examples/chat-app/app/hyperloop/components/app.rb +11 -0
- data/examples/chat-app/app/hyperloop/components/formatted_div.rb +13 -0
- data/examples/chat-app/app/hyperloop/components/input_box.rb +29 -0
- data/examples/chat-app/app/hyperloop/components/message.rb +29 -0
- data/examples/chat-app/app/hyperloop/components/messages.rb +9 -0
- data/examples/chat-app/app/hyperloop/components/nav.rb +30 -0
- data/examples/chat-app/app/hyperloop/operations/operations.rb +56 -0
- data/examples/chat-app/app/hyperloop/stores/message_store.rb +23 -0
- data/examples/chat-app/app/models/application_record.rb +3 -0
- data/examples/chat-app/app/models/concerns/.keep +0 -0
- data/examples/chat-app/app/models/models.rb +2 -0
- data/examples/chat-app/app/models/public/.keep +0 -0
- data/examples/chat-app/app/models/public/announcement.rb +8 -0
- data/examples/chat-app/app/policies/application_policy.rb +5 -0
- data/examples/chat-app/app/views/layouts/application.html.erb +51 -0
- data/examples/chat-app/bin/bundle +3 -0
- data/examples/chat-app/bin/rails +9 -0
- data/examples/chat-app/bin/rake +9 -0
- data/examples/chat-app/bin/setup +34 -0
- data/examples/chat-app/bin/spring +17 -0
- data/examples/chat-app/bin/update +29 -0
- data/examples/chat-app/config.ru +5 -0
- data/examples/chat-app/config/application.rb +13 -0
- data/examples/chat-app/config/boot.rb +3 -0
- data/examples/chat-app/config/cable.yml +9 -0
- data/examples/chat-app/config/database.yml +25 -0
- data/examples/chat-app/config/environment.rb +5 -0
- data/examples/chat-app/config/environments/development.rb +56 -0
- data/examples/chat-app/config/environments/production.rb +86 -0
- data/examples/chat-app/config/environments/test.rb +42 -0
- data/examples/chat-app/config/initializers/application_controller_renderer.rb +6 -0
- data/examples/chat-app/config/initializers/assets.rb +11 -0
- data/examples/chat-app/config/initializers/backtrace_silencers.rb +7 -0
- data/examples/chat-app/config/initializers/cookies_serializer.rb +5 -0
- data/examples/chat-app/config/initializers/filter_parameter_logging.rb +4 -0
- data/examples/chat-app/config/initializers/hyperloop.rb +4 -0
- data/examples/chat-app/config/initializers/inflections.rb +16 -0
- data/examples/chat-app/config/initializers/mime_types.rb +4 -0
- data/examples/chat-app/config/initializers/new_framework_defaults.rb +24 -0
- data/examples/chat-app/config/initializers/session_store.rb +3 -0
- data/examples/chat-app/config/initializers/wrap_parameters.rb +14 -0
- data/examples/chat-app/config/locales/en.yml +23 -0
- data/examples/chat-app/config/puma.rb +47 -0
- data/examples/chat-app/config/routes.rb +5 -0
- data/examples/chat-app/config/secrets.yml +22 -0
- data/examples/chat-app/config/spring.rb +6 -0
- data/examples/chat-app/db/seeds.rb +7 -0
- data/examples/chat-app/lib/assets/.keep +0 -0
- data/examples/chat-app/lib/tasks/.keep +0 -0
- data/examples/chat-app/log/.keep +0 -0
- data/examples/chat-app/public/404.html +67 -0
- data/examples/chat-app/public/422.html +67 -0
- data/examples/chat-app/public/500.html +66 -0
- data/examples/chat-app/public/apple-touch-icon-precomposed.png +0 -0
- data/examples/chat-app/public/apple-touch-icon.png +0 -0
- data/examples/chat-app/public/favicon.ico +0 -0
- data/examples/chat-app/public/robots.txt +5 -0
- data/examples/chat-app/test/controllers/.keep +0 -0
- data/examples/chat-app/test/fixtures/.keep +0 -0
- data/examples/chat-app/test/fixtures/files/.keep +0 -0
- data/examples/chat-app/test/helpers/.keep +0 -0
- data/examples/chat-app/test/integration/.keep +0 -0
- data/examples/chat-app/test/mailers/.keep +0 -0
- data/examples/chat-app/test/models/.keep +0 -0
- data/examples/chat-app/test/test_helper.rb +10 -0
- data/examples/chat-app/tmp/.keep +0 -0
- data/examples/chat-app/vendor/assets/javascripts/.keep +0 -0
- data/examples/chat-app/vendor/assets/stylesheets/.keep +0 -0
- data/examples/five-letter-word-game/.gitignore +21 -0
- data/examples/five-letter-word-game/Gemfile +57 -0
- data/examples/five-letter-word-game/Gemfile.lock +282 -0
- data/examples/five-letter-word-game/README.md +24 -0
- data/examples/five-letter-word-game/Rakefile +6 -0
- data/examples/five-letter-word-game/app/assets/config/manifest.js +3 -0
- data/examples/five-letter-word-game/app/assets/images/.keep +0 -0
- data/examples/five-letter-word-game/app/assets/javascripts/application.js +3 -0
- data/examples/five-letter-word-game/app/assets/javascripts/cable.js +13 -0
- data/examples/five-letter-word-game/app/assets/javascripts/channels/.keep +0 -0
- data/examples/five-letter-word-game/app/assets/stylesheets/application.css +15 -0
- data/examples/five-letter-word-game/app/channels/application_cable/channel.rb +4 -0
- data/examples/five-letter-word-game/app/channels/application_cable/connection.rb +4 -0
- data/examples/five-letter-word-game/app/controllers/application_controller.rb +14 -0
- data/examples/five-letter-word-game/app/controllers/concerns/.keep +0 -0
- data/examples/five-letter-word-game/app/controllers/home_controller.rb +5 -0
- data/examples/five-letter-word-game/app/helpers/application_helper.rb +2 -0
- data/examples/five-letter-word-game/app/hyperloop/components/app.rb +65 -0
- data/examples/five-letter-word-game/app/hyperloop/components/guesses.rb +8 -0
- data/examples/five-letter-word-game/app/hyperloop/components/input_word.rb +13 -0
- data/examples/five-letter-word-game/app/hyperloop/models/user.rb +27 -0
- data/examples/five-letter-word-game/app/hyperloop/operations/ops.rb +115 -0
- data/examples/five-letter-word-game/app/hyperloop/stores/store.rb +120 -0
- data/examples/five-letter-word-game/app/jobs/application_job.rb +2 -0
- data/examples/five-letter-word-game/app/mailers/application_mailer.rb +4 -0
- data/examples/five-letter-word-game/app/models/application_record.rb +3 -0
- data/examples/five-letter-word-game/app/models/concerns/.keep +0 -0
- data/examples/five-letter-word-game/app/policies/user_policy.rb +4 -0
- data/examples/five-letter-word-game/app/views/layouts/application.html.erb +14 -0
- data/examples/five-letter-word-game/app/views/layouts/mailer.html.erb +13 -0
- data/examples/five-letter-word-game/app/views/layouts/mailer.text.erb +1 -0
- data/examples/five-letter-word-game/bin/bundle +3 -0
- data/examples/five-letter-word-game/bin/rails +9 -0
- data/examples/five-letter-word-game/bin/rake +9 -0
- data/examples/five-letter-word-game/bin/setup +34 -0
- data/examples/five-letter-word-game/bin/spring +17 -0
- data/examples/five-letter-word-game/bin/update +29 -0
- data/examples/five-letter-word-game/config.ru +5 -0
- data/examples/five-letter-word-game/config/application.rb +12 -0
- data/examples/five-letter-word-game/config/boot.rb +3 -0
- data/examples/five-letter-word-game/config/cable.yml +9 -0
- data/examples/five-letter-word-game/config/database.yml +25 -0
- data/examples/five-letter-word-game/config/environment.rb +5 -0
- data/examples/five-letter-word-game/config/environments/development.rb +56 -0
- data/examples/five-letter-word-game/config/environments/production.rb +86 -0
- data/examples/five-letter-word-game/config/environments/test.rb +42 -0
- data/examples/five-letter-word-game/config/initializers/application_controller_renderer.rb +6 -0
- data/examples/five-letter-word-game/config/initializers/assets.rb +11 -0
- data/examples/five-letter-word-game/config/initializers/backtrace_silencers.rb +7 -0
- data/examples/five-letter-word-game/config/initializers/cookies_serializer.rb +5 -0
- data/examples/five-letter-word-game/config/initializers/filter_parameter_logging.rb +4 -0
- data/examples/five-letter-word-game/config/initializers/hyperloop.rb +3 -0
- data/examples/five-letter-word-game/config/initializers/inflections.rb +16 -0
- data/examples/five-letter-word-game/config/initializers/mime_types.rb +4 -0
- data/examples/five-letter-word-game/config/initializers/new_framework_defaults.rb +24 -0
- data/examples/five-letter-word-game/config/initializers/session_store.rb +3 -0
- data/examples/five-letter-word-game/config/initializers/wrap_parameters.rb +14 -0
- data/examples/five-letter-word-game/config/locales/en.yml +23 -0
- data/examples/five-letter-word-game/config/puma.rb +47 -0
- data/examples/five-letter-word-game/config/routes.rb +5 -0
- data/examples/five-letter-word-game/config/secrets.yml +22 -0
- data/examples/five-letter-word-game/config/spring.rb +6 -0
- data/examples/five-letter-word-game/db/schema.rb +28 -0
- data/examples/five-letter-word-game/db/seeds.rb +7 -0
- data/examples/five-letter-word-game/lib/assets/.keep +0 -0
- data/examples/five-letter-word-game/lib/tasks/.keep +0 -0
- data/examples/five-letter-word-game/log/.keep +0 -0
- data/examples/five-letter-word-game/public/404.html +67 -0
- data/examples/five-letter-word-game/public/422.html +67 -0
- data/examples/five-letter-word-game/public/500.html +66 -0
- data/examples/five-letter-word-game/public/apple-touch-icon-precomposed.png +0 -0
- data/examples/five-letter-word-game/public/apple-touch-icon.png +0 -0
- data/examples/five-letter-word-game/public/favicon.ico +0 -0
- data/examples/five-letter-word-game/public/robots.txt +5 -0
- data/examples/five-letter-word-game/test/controllers/.keep +0 -0
- data/examples/five-letter-word-game/test/fixtures/.keep +0 -0
- data/examples/five-letter-word-game/test/fixtures/files/.keep +0 -0
- data/examples/five-letter-word-game/test/helpers/.keep +0 -0
- data/examples/five-letter-word-game/test/integration/.keep +0 -0
- data/examples/five-letter-word-game/test/mailers/.keep +0 -0
- data/examples/five-letter-word-game/test/models/.keep +0 -0
- data/examples/five-letter-word-game/test/test_helper.rb +10 -0
- data/examples/five-letter-word-game/tmp/.keep +0 -0
- data/examples/five-letter-word-game/vendor/assets/javascripts/.keep +0 -0
- data/examples/five-letter-word-game/vendor/assets/stylesheets/.keep +0 -0
- data/examples/smoke_test/.gitignore +21 -0
- data/examples/smoke_test/Gemfile +59 -0
- data/examples/smoke_test/Gemfile.lock +289 -0
- data/examples/smoke_test/README.md +24 -0
- data/examples/smoke_test/Rakefile +6 -0
- data/examples/smoke_test/app/assets/config/manifest.js +3 -0
- data/examples/smoke_test/app/assets/images/.keep +0 -0
- data/examples/smoke_test/app/assets/javascripts/application.js +15 -0
- data/examples/smoke_test/app/assets/javascripts/cable.js +13 -0
- data/examples/smoke_test/app/assets/javascripts/channels/.keep +0 -0
- data/examples/smoke_test/app/assets/stylesheets/application.css +15 -0
- data/examples/smoke_test/app/channels/application_cable/channel.rb +4 -0
- data/examples/smoke_test/app/channels/application_cable/connection.rb +4 -0
- data/examples/smoke_test/app/controllers/app_controller.rb +5 -0
- data/examples/smoke_test/app/controllers/application_controller.rb +3 -0
- data/examples/smoke_test/app/helpers/application_helper.rb +2 -0
- data/examples/smoke_test/app/hyperloop/components/hello.rb +25 -0
- data/examples/smoke_test/app/hyperloop/operations/operations/nested_send_to_all.rb +7 -0
- data/examples/smoke_test/app/hyperloop/operations/send_to_all.rb +6 -0
- data/examples/smoke_test/app/hyperloop/stores/messages.rb +4 -0
- data/examples/smoke_test/app/jobs/application_job.rb +2 -0
- data/examples/smoke_test/app/mailers/application_mailer.rb +4 -0
- data/examples/smoke_test/app/models/application_record.rb +3 -0
- data/examples/smoke_test/app/models/concerns/.keep +0 -0
- data/examples/smoke_test/app/policies/application_policy.rb +8 -0
- data/examples/smoke_test/app/views/layouts/application.html.erb +14 -0
- data/examples/smoke_test/app/views/layouts/mailer.html.erb +13 -0
- data/examples/smoke_test/app/views/layouts/mailer.text.erb +1 -0
- data/examples/smoke_test/bin/bundle +3 -0
- data/examples/smoke_test/bin/rails +9 -0
- data/examples/smoke_test/bin/rake +9 -0
- data/examples/smoke_test/bin/setup +34 -0
- data/examples/smoke_test/bin/spring +17 -0
- data/examples/smoke_test/bin/update +29 -0
- data/examples/smoke_test/config.ru +5 -0
- data/examples/smoke_test/config/application.rb +15 -0
- data/examples/smoke_test/config/boot.rb +3 -0
- data/examples/smoke_test/config/cable.yml +9 -0
- data/examples/smoke_test/config/database.yml +25 -0
- data/examples/smoke_test/config/environment.rb +5 -0
- data/examples/smoke_test/config/environments/development.rb +54 -0
- data/examples/smoke_test/config/environments/production.rb +86 -0
- data/examples/smoke_test/config/environments/test.rb +42 -0
- data/examples/smoke_test/config/initializers/application_controller_renderer.rb +6 -0
- data/examples/smoke_test/config/initializers/assets.rb +11 -0
- data/examples/smoke_test/config/initializers/backtrace_silencers.rb +7 -0
- data/examples/smoke_test/config/initializers/cookies_serializer.rb +5 -0
- data/examples/smoke_test/config/initializers/filter_parameter_logging.rb +4 -0
- data/examples/smoke_test/config/initializers/hyperloop.rb +32 -0
- data/examples/smoke_test/config/initializers/inflections.rb +16 -0
- data/examples/smoke_test/config/initializers/mime_types.rb +4 -0
- data/examples/smoke_test/config/initializers/new_framework_defaults.rb +24 -0
- data/examples/smoke_test/config/initializers/session_store.rb +3 -0
- data/examples/smoke_test/config/initializers/wrap_parameters.rb +14 -0
- data/examples/smoke_test/config/locales/en.yml +23 -0
- data/examples/smoke_test/config/puma.rb +47 -0
- data/examples/smoke_test/config/routes.rb +5 -0
- data/examples/smoke_test/config/secrets.yml +22 -0
- data/examples/smoke_test/config/spring.rb +6 -0
- data/examples/smoke_test/db/seeds.rb +7 -0
- data/examples/smoke_test/lib/assets/.keep +0 -0
- data/examples/smoke_test/lib/tasks/.keep +0 -0
- data/examples/smoke_test/log/.keep +0 -0
- data/examples/smoke_test/public/404.html +67 -0
- data/examples/smoke_test/public/422.html +67 -0
- data/examples/smoke_test/public/500.html +66 -0
- data/examples/smoke_test/public/apple-touch-icon-precomposed.png +0 -0
- data/examples/smoke_test/public/apple-touch-icon.png +0 -0
- data/examples/smoke_test/public/favicon.ico +0 -0
- data/examples/smoke_test/public/robots.txt +5 -0
- data/examples/smoke_test/test/controllers/.keep +0 -0
- data/examples/smoke_test/test/fixtures/.keep +0 -0
- data/examples/smoke_test/test/fixtures/files/.keep +0 -0
- data/examples/smoke_test/test/helpers/.keep +0 -0
- data/examples/smoke_test/test/integration/.keep +0 -0
- data/examples/smoke_test/test/mailers/.keep +0 -0
- data/examples/smoke_test/test/models/.keep +0 -0
- data/examples/smoke_test/test/test_helper.rb +10 -0
- data/examples/smoke_test/tmp/.keep +0 -0
- data/examples/smoke_test/vendor/assets/javascripts/.keep +0 -0
- data/examples/smoke_test/vendor/assets/stylesheets/.keep +0 -0
- data/hyper-operation.gemspec +44 -0
- data/lib/hyper-operation.rb +59 -0
- data/lib/hyper-operation/api.rb +154 -0
- data/lib/hyper-operation/boot.rb +24 -0
- data/lib/hyper-operation/call_by_class_name.rb +60 -0
- data/lib/hyper-operation/delay_and_interval.rb +9 -0
- data/lib/hyper-operation/engine.rb +11 -0
- data/lib/hyper-operation/exception.rb +13 -0
- data/lib/hyper-operation/filters/acting_user.rb +19 -0
- data/lib/hyper-operation/filters/outbound_filter.rb +9 -0
- data/lib/hyper-operation/filters/simple_hash.rb +22 -0
- data/lib/hyper-operation/opal_patches.rb +39 -0
- data/lib/hyper-operation/promise.rb +347 -0
- data/lib/hyper-operation/railway.rb +5 -0
- data/lib/hyper-operation/railway/dispatcher.rb +31 -0
- data/lib/hyper-operation/railway/operation_wrapper.rb +106 -0
- data/lib/hyper-operation/railway/params_wrapper.rb +124 -0
- data/lib/hyper-operation/railway/run.rb +140 -0
- data/lib/hyper-operation/railway/validations.rb +63 -0
- data/lib/hyper-operation/server_op.rb +98 -0
- data/lib/hyper-operation/transport/acting_user.rb +6 -0
- data/lib/hyper-operation/transport/action_cable.rb +39 -0
- data/lib/hyper-operation/transport/active_record.rb +15 -0
- data/lib/hyper-operation/transport/client_drivers.rb +210 -0
- data/lib/hyper-operation/transport/connection.rb +170 -0
- data/lib/hyper-operation/transport/hyperloop.rb +165 -0
- data/lib/hyper-operation/transport/hyperloop_controller.rb +184 -0
- data/lib/hyper-operation/transport/pluck.rb +6 -0
- data/lib/hyper-operation/transport/policy.rb +535 -0
- data/lib/hyper-operation/version.rb +5 -0
- data/lib/sources/hyperloop/pusher.js +98 -0
- metadata +628 -0
@@ -0,0 +1,31 @@
|
|
1
|
+
module Hyperloop
|
2
|
+
class Operation
|
3
|
+
class Railway
|
4
|
+
|
5
|
+
def receivers
|
6
|
+
self.class.receivers
|
7
|
+
end
|
8
|
+
|
9
|
+
class << self
|
10
|
+
def receivers
|
11
|
+
@receivers ||= []
|
12
|
+
end
|
13
|
+
|
14
|
+
def add_receiver(&block)
|
15
|
+
receivers << block
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
def dispatch
|
20
|
+
result.then do
|
21
|
+
receivers.each do |receiver|
|
22
|
+
receiver.call(
|
23
|
+
self.class.params_wrapper.dispatch_params(@operation.params),
|
24
|
+
@operation
|
25
|
+
)
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,106 @@
|
|
1
|
+
# module Hyperloop
|
2
|
+
# class Operation
|
3
|
+
# class Railway
|
4
|
+
#
|
5
|
+
# class Exit < StandardError
|
6
|
+
# attr_reader :state
|
7
|
+
# attr_reader :result
|
8
|
+
# def initialize(state, result)
|
9
|
+
# @state = state
|
10
|
+
# @result = result
|
11
|
+
# end
|
12
|
+
# end
|
13
|
+
#
|
14
|
+
# class << self
|
15
|
+
# def add_param(*args, &block)
|
16
|
+
# Hyperloop::Operation::ParamsWrapper.add_param(hash_filter, *args, &block)
|
17
|
+
# end
|
18
|
+
#
|
19
|
+
# def add_validation(*args, &block)
|
20
|
+
# validations << [args, block]
|
21
|
+
# end
|
22
|
+
#
|
23
|
+
# def add_error(param, symbol, message, *args, &block)
|
24
|
+
# add_validation do
|
25
|
+
# add_error(param, symbol, message) if call_block_with_context(args, block)
|
26
|
+
# end
|
27
|
+
# end
|
28
|
+
#
|
29
|
+
# def add_step(*args, &block)
|
30
|
+
# railway << [:step, args, block]
|
31
|
+
# end
|
32
|
+
#
|
33
|
+
# def add_failed(*args, &block)
|
34
|
+
# railway << [:failed, args, block]
|
35
|
+
# end
|
36
|
+
#
|
37
|
+
# def add_async(*args, &block)
|
38
|
+
# railway << [:async, args, block]
|
39
|
+
# end
|
40
|
+
#
|
41
|
+
# def apply(op, state, result, args, block)
|
42
|
+
# if block.arity == 0
|
43
|
+
# [state, op.instance_eval &block]
|
44
|
+
# elsif result.is_a? Array && block.arity == result.count
|
45
|
+
# [state, op.instance_exec(*result, &block)]
|
46
|
+
# else
|
47
|
+
# [state, op.instance_exec(result, block)]
|
48
|
+
# end
|
49
|
+
# rescue Exception => e
|
50
|
+
# [:failed, e]
|
51
|
+
# end
|
52
|
+
#
|
53
|
+
# def run(op)
|
54
|
+
# state = :success # or :failed if @errors
|
55
|
+
# result = nil
|
56
|
+
# railway.each do |tie|
|
57
|
+
# case tie[0]
|
58
|
+
# when :step
|
59
|
+
# if result.is_a? Promise
|
60
|
+
# result = result.then { |*result| apply(op, :success, result, *tie[1..2]) }
|
61
|
+
# elsif state == :success
|
62
|
+
# state, result = apply(op, state, result, tie[1], tie[2])
|
63
|
+
# end
|
64
|
+
# when :failed
|
65
|
+
# if result.is_a? Promise
|
66
|
+
# result = result.fail { |*result| apply(op, :failed, result, *tie[1..2]) }
|
67
|
+
# elsif state == :failed
|
68
|
+
# state, result = apply(op, state, result, tie[1], tie[2])
|
69
|
+
# end
|
70
|
+
# when :async
|
71
|
+
# state, result = apply(op, state, result, tie[1], tie[2]) if state != :failed
|
72
|
+
# end
|
73
|
+
# end
|
74
|
+
# rescue Hyperloop::Operation::Wrapper::Exit => e
|
75
|
+
# result, state = [e.result, e.state]
|
76
|
+
# ensure
|
77
|
+
# if result.is_a? Promise
|
78
|
+
# result
|
79
|
+
# elsif state == :failed
|
80
|
+
# Promise.new.reject(result)
|
81
|
+
# else
|
82
|
+
# Promise.new.resolve(result)
|
83
|
+
# end
|
84
|
+
# end
|
85
|
+
#
|
86
|
+
#
|
87
|
+
#
|
88
|
+
#
|
89
|
+
# # THIS SHOULD BE ADDED ONLY IN ServerOps
|
90
|
+
# def dispatch_to(*args, &block)
|
91
|
+
# dispatches << [args, block]
|
92
|
+
# end
|
93
|
+
#
|
94
|
+
# def hash_filter
|
95
|
+
# @hash_filter ||= Mutations::HashFilter.new
|
96
|
+
# end
|
97
|
+
#
|
98
|
+
# def validations
|
99
|
+
# @validations ||= []
|
100
|
+
# end
|
101
|
+
#
|
102
|
+
#
|
103
|
+
#
|
104
|
+
# def dispatches
|
105
|
+
# @dispatches ||= []
|
106
|
+
# end
|
@@ -0,0 +1,124 @@
|
|
1
|
+
module Hyperloop
|
2
|
+
class Operation
|
3
|
+
class ParamsWrapper
|
4
|
+
|
5
|
+
def initialize(inputs)
|
6
|
+
@inputs = inputs
|
7
|
+
end
|
8
|
+
|
9
|
+
def lock
|
10
|
+
@locked = true
|
11
|
+
self
|
12
|
+
end
|
13
|
+
|
14
|
+
def to_h
|
15
|
+
@inputs.with_indifferent_access
|
16
|
+
end
|
17
|
+
|
18
|
+
def to_s
|
19
|
+
to_h.to_s
|
20
|
+
end
|
21
|
+
|
22
|
+
class << self
|
23
|
+
|
24
|
+
def combine_arg_array(args)
|
25
|
+
hash = args.inject({}.with_indifferent_access) do |h, arg|
|
26
|
+
raise ArgumentError.new("All arguments must be hashes") unless arg.respond_to? :to_h
|
27
|
+
h.merge!(arg.to_h)
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
def process_params(operation, args)
|
32
|
+
raw_inputs = combine_arg_array(args)
|
33
|
+
inputs, errors = hash_filter.filter(raw_inputs)
|
34
|
+
params_wrapper = new(inputs)
|
35
|
+
operation.instance_eval do
|
36
|
+
@raw_inputs, @params, @errors = [raw_inputs, params_wrapper, errors]
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
def add_param(*args, &block)
|
41
|
+
type_method, name, opts, block = translate_args(*args, &block)
|
42
|
+
if opts.key? :default
|
43
|
+
hash_filter.optional { send(type_method, name, opts, &block) }
|
44
|
+
else
|
45
|
+
hash_filter.required { send(type_method, name, opts, &block) }
|
46
|
+
end
|
47
|
+
|
48
|
+
# don't forget specially handling for procs
|
49
|
+
define_method(name) do
|
50
|
+
@inputs[name]
|
51
|
+
end
|
52
|
+
define_method(:"#{name}=") do |x|
|
53
|
+
method_missing(:"#{name}=", x) if @locked
|
54
|
+
@inputs[name] = x
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
def dispatch_params(params, hashes = {})
|
59
|
+
params = params.dup
|
60
|
+
hashes.each { |hash| hash.each { |k, v| params.send(:"#{k}=", v) } }
|
61
|
+
params.lock
|
62
|
+
end
|
63
|
+
|
64
|
+
def hash_filter
|
65
|
+
@hash_filter ||= Mutations::HashFilter.new
|
66
|
+
end
|
67
|
+
|
68
|
+
def translate_args(*args, &block)
|
69
|
+
name, opts = get_name_and_opts(*args)
|
70
|
+
if opts.key?(:type)
|
71
|
+
type_method = opts.delete(:type)
|
72
|
+
if type_method.is_a?(Array)
|
73
|
+
opts[:class] = type_method.first if type_method.count > 0
|
74
|
+
type_method = Array
|
75
|
+
elsif type_method.is_a?(Hash) || type_method == Hash
|
76
|
+
type_method = Hash
|
77
|
+
block ||= proc { duck :* }
|
78
|
+
end
|
79
|
+
type_method = type_method.to_s.underscore
|
80
|
+
else
|
81
|
+
type_method = :duck
|
82
|
+
end
|
83
|
+
[type_method, name, opts, block || proc {}]
|
84
|
+
end
|
85
|
+
|
86
|
+
def get_name_and_opts(*args)
|
87
|
+
if args[0].is_a? Hash
|
88
|
+
opts = args[0]
|
89
|
+
name = opts.first.first
|
90
|
+
opts[:default] = opts.first.last
|
91
|
+
opts.delete(name)
|
92
|
+
else
|
93
|
+
name = args[0]
|
94
|
+
opts = args[1] || {}
|
95
|
+
end
|
96
|
+
[name, opts]
|
97
|
+
end
|
98
|
+
end
|
99
|
+
end
|
100
|
+
|
101
|
+
class Railway
|
102
|
+
def process_params(args)
|
103
|
+
self.class.params_wrapper.process_params(@operation, args)
|
104
|
+
end
|
105
|
+
|
106
|
+
def self.add_param(*args, &block)
|
107
|
+
params_wrapper.add_param(*args, &block)
|
108
|
+
end
|
109
|
+
|
110
|
+
def self.params_wrapper
|
111
|
+
@params_wrapper ||= begin
|
112
|
+
if Railway == superclass
|
113
|
+
Class.new(ParamsWrapper)
|
114
|
+
else
|
115
|
+
Class.new(superclass.params_wrapper).tap do |wrapper|
|
116
|
+
hash_filter = superclass.params_wrapper.hash_filter
|
117
|
+
wrapper.instance_variable_set('@hash_filter', hash_filter && hash_filter.dup)
|
118
|
+
end
|
119
|
+
end
|
120
|
+
end
|
121
|
+
end
|
122
|
+
end
|
123
|
+
end
|
124
|
+
end
|
@@ -0,0 +1,140 @@
|
|
1
|
+
module Hyperloop
|
2
|
+
class Operation
|
3
|
+
|
4
|
+
class Exit < StandardError
|
5
|
+
attr_reader :state
|
6
|
+
attr_reader :result
|
7
|
+
def initialize(state, result)
|
8
|
+
@state = state
|
9
|
+
@result = result
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
class Railway
|
14
|
+
|
15
|
+
def tracks
|
16
|
+
self.class.tracks
|
17
|
+
end
|
18
|
+
|
19
|
+
class << self
|
20
|
+
def tracks
|
21
|
+
@tracks ||= []
|
22
|
+
end
|
23
|
+
|
24
|
+
def to_opts(tie, args, block)
|
25
|
+
if args.count.zero?
|
26
|
+
{ run: block }
|
27
|
+
elsif args[0].is_a?(Hash)
|
28
|
+
{
|
29
|
+
scope: args[0][:class] ? :class : args[0][:scope],
|
30
|
+
run: args[0][:class] || args[0][:run] || block
|
31
|
+
}
|
32
|
+
elsif args[0] == :class && block
|
33
|
+
{ run: block, scope: :class }
|
34
|
+
elsif args[0].is_a?(Class) && args[0] < Operation
|
35
|
+
{ run: proc { args[0].run(params) } }
|
36
|
+
else
|
37
|
+
scope = args[1][:scope] if args[1].is_a? Hash
|
38
|
+
{ run: args[0], scope: scope }
|
39
|
+
end.merge(tie: instance_method(tie))
|
40
|
+
end
|
41
|
+
|
42
|
+
[:step, :failed, :async].each do |tie|
|
43
|
+
define_method :"add_#{tie}" do |*args, &block|
|
44
|
+
tracks << to_opts(tie, args, block)
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
def abort!(arg)
|
49
|
+
raise Exit.new(:failed, arg)
|
50
|
+
end
|
51
|
+
|
52
|
+
def succeed!(arg)
|
53
|
+
raise Exit.new(:success, arg)
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
def step(opts)
|
58
|
+
if @last_result.is_a? Promise
|
59
|
+
@last_result = @last_result.then do |*result|
|
60
|
+
@last_result = result
|
61
|
+
apply(opts, :in_promise)
|
62
|
+
end
|
63
|
+
elsif @state == :success
|
64
|
+
apply(opts)
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
def failed(opts)
|
69
|
+
if @last_result.is_a? Promise
|
70
|
+
@last_result = @last_result.fail do |e|
|
71
|
+
@last_result = e
|
72
|
+
apply(opts, :in_promise)
|
73
|
+
raise @last_result if @last_result.is_a? Exception
|
74
|
+
raise e
|
75
|
+
end
|
76
|
+
elsif @state == :failed
|
77
|
+
apply(opts)
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
def async(opts)
|
82
|
+
apply(opts) if @state != :failed
|
83
|
+
end
|
84
|
+
|
85
|
+
def apply(opts, in_promise = nil)
|
86
|
+
if opts[:scope] == :class
|
87
|
+
args = [@operation, *@last_result]
|
88
|
+
instance = @operation.class
|
89
|
+
else
|
90
|
+
args = @last_result
|
91
|
+
instance = @operation
|
92
|
+
end
|
93
|
+
block = opts[:run]
|
94
|
+
block = instance.method(block) if block.is_a? Symbol
|
95
|
+
@last_result =
|
96
|
+
if block.arity.zero?
|
97
|
+
instance.instance_exec(&block)
|
98
|
+
elsif args.is_a?(Array) && block.arity == args.count
|
99
|
+
instance.instance_exec(*args, &block)
|
100
|
+
else
|
101
|
+
instance.instance_exec(args, &block)
|
102
|
+
end
|
103
|
+
return @last_result unless @last_result.is_a? Promise
|
104
|
+
raise @last_result.error if @last_result.rejected?
|
105
|
+
@last_result = @last_result.value if @last_result.resolved?
|
106
|
+
@last_result
|
107
|
+
rescue Exit => e
|
108
|
+
@state = e.state
|
109
|
+
@last_result = (e.state != :failed || e.result.is_a?(Exception)) ? e.result : e
|
110
|
+
raise e
|
111
|
+
rescue Exception => e
|
112
|
+
@state = :failed
|
113
|
+
@last_result = e
|
114
|
+
raise e if in_promise
|
115
|
+
end
|
116
|
+
|
117
|
+
def run
|
118
|
+
if @operation.has_errors? || @state
|
119
|
+
@last_result ||= ValidationException.new(@operation.instance_variable_get('@errors'))
|
120
|
+
return if @state # handles abort out of validation
|
121
|
+
@state = :failed
|
122
|
+
else
|
123
|
+
@state = :success
|
124
|
+
end
|
125
|
+
tracks.each { |opts| opts[:tie].bind(self).call(opts) }
|
126
|
+
rescue Exit
|
127
|
+
end
|
128
|
+
|
129
|
+
def result
|
130
|
+
return @last_result if @last_result.is_a? Promise
|
131
|
+
@last_result =
|
132
|
+
if @state == :success
|
133
|
+
Promise.new.resolve(@last_result)
|
134
|
+
else
|
135
|
+
Promise.new.reject(@last_result)
|
136
|
+
end
|
137
|
+
end
|
138
|
+
end
|
139
|
+
end
|
140
|
+
end
|
@@ -0,0 +1,63 @@
|
|
1
|
+
module Hyperloop
|
2
|
+
class Operation
|
3
|
+
class Railway
|
4
|
+
|
5
|
+
def validations
|
6
|
+
self.class.validations
|
7
|
+
end
|
8
|
+
|
9
|
+
def add_validation_error(i, e)
|
10
|
+
@operation.add_error("param validation #{i+1}", :validation_error, e.to_s)
|
11
|
+
end
|
12
|
+
|
13
|
+
class << self
|
14
|
+
def validations
|
15
|
+
@validations ||= []
|
16
|
+
end
|
17
|
+
|
18
|
+
def add_validation(*args, &block)
|
19
|
+
block = args[0] if args[0]
|
20
|
+
validations << block
|
21
|
+
end
|
22
|
+
|
23
|
+
def add_error(param, symbol, message, *args, &block)
|
24
|
+
add_validation do
|
25
|
+
begin
|
26
|
+
add_error(param, symbol, message) if instance_eval(&block)
|
27
|
+
rescue Exit => e
|
28
|
+
raise e unless e.state == :failed
|
29
|
+
add_error(param, symbol, message)
|
30
|
+
raise Exit.new(:abort_from_add_error, e.result)
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
def process_validations
|
37
|
+
validations.each_with_index do |validator, i|
|
38
|
+
begin
|
39
|
+
validator = @operation.method(validator) if validator.is_a? Symbol
|
40
|
+
next if @operation.instance_exec(&validator)
|
41
|
+
add_validation_error(i, "param validation #{i+1} failed")
|
42
|
+
rescue Exit => e
|
43
|
+
case e.state
|
44
|
+
when :success
|
45
|
+
add_validation_error(i, "illegal use of succeed! in validation")
|
46
|
+
when :failed
|
47
|
+
add_validation_error(i, "param validation #{i+1} aborted")
|
48
|
+
end
|
49
|
+
@state = :failed
|
50
|
+
return # break does not work in Opal
|
51
|
+
rescue AccessViolation => e
|
52
|
+
add_validation_error(i, e)
|
53
|
+
@state = :failed
|
54
|
+
@last_result = e
|
55
|
+
return # break does not work in Opal
|
56
|
+
rescue Exception => e
|
57
|
+
add_validation_error(i, e)
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|