|
# frozen_string_literal: true |
|
|
|
require 'rubygems' |
|
require 'bundler/setup' |
|
|
|
# require your gems as usual |
|
Bundler.require(:default) |
|
|
|
(1..20).each do |n| |
|
Object.const_set("Action#{n}", Class.new do |
|
extend LightService::Action |
|
expects :foo |
|
|
|
executed do |context| |
|
context.foo << name |
|
p "Action -#{name}- called. Context: #{context}" |
|
end |
|
end) |
|
end |
|
|
|
module Runnable |
|
def run(action, context) |
|
case action |
|
in LightService::Action |
|
return action.execute(context) |
|
in Member |
|
return action.call(context) |
|
in Sequence |
|
return action.with(context).call |
|
in Proc |
|
action.call(context) |
|
return context |
|
end |
|
|
|
raise ArgumentError |
|
end |
|
private :run |
|
end |
|
|
|
class Sequence |
|
include Runnable |
|
|
|
attr_reader :members, :context |
|
attr_accessor :before_actions, :after_actions |
|
|
|
class << self |
|
def[](*actions) |
|
new[*actions] |
|
end |
|
end |
|
|
|
def [](*actions) |
|
@before_actions = [] |
|
@after_actions = [] |
|
@members = actions.map do |action| |
|
next action if action.is_a?(Sequence) |
|
next action if action.is_a?(Member) |
|
|
|
next Member.new(action) if action.is_a?(LightService::Action) |
|
|
|
raise ArgumentError |
|
end |
|
|
|
self |
|
end |
|
|
|
def with(context) |
|
@context = LightService::Context.make(context) |
|
|
|
self |
|
end |
|
|
|
def after(*actions) |
|
@after_actions = (after_actions + actions).flatten |
|
|
|
self |
|
end |
|
|
|
def before(*actions) |
|
@before_actions = (before_actions + actions).flatten |
|
|
|
self |
|
end |
|
|
|
def after_each(*actions) |
|
@members.each do |member| |
|
member.after(actions) |
|
end |
|
|
|
self |
|
end |
|
|
|
def before_each(*actions) |
|
@members.each do |member| |
|
member.before(actions) |
|
end |
|
|
|
self |
|
end |
|
|
|
def call |
|
before_actions.each do |action| |
|
@context = run(action, context) |
|
end |
|
|
|
members.each do |member| |
|
@context = run(member, context) |
|
end |
|
|
|
after_actions.each do |action| |
|
@context = run(action, context) |
|
end |
|
|
|
@context |
|
end |
|
|
|
def flatten |
|
FlatMap.new(self).map |
|
end |
|
end |
|
|
|
class Member |
|
include Runnable |
|
|
|
attr_reader :action, :before_actions, :after_actions |
|
|
|
def initialize(action) |
|
@action = action |
|
@before_actions = [] |
|
@after_actions = [] |
|
end |
|
|
|
def call(context) |
|
before_actions.each do |action| |
|
context = run(action, context) |
|
end |
|
|
|
context = run(action, context) |
|
|
|
after_actions.each do |action| |
|
context = run(action, context) |
|
end |
|
|
|
context |
|
end |
|
|
|
def flatten |
|
FlatMap.new(self).to_a |
|
end |
|
|
|
def after(*actions) |
|
@after_actions = (after_actions + actions).flatten |
|
|
|
self |
|
end |
|
|
|
def before(*actions) |
|
@before_actions = (before_actions + actions).flatten |
|
|
|
self |
|
end |
|
end |
|
|
|
class FlatMap |
|
attr_reader :map, :mappable |
|
|
|
def initialize(mappable) |
|
@map = [] |
|
@mappable = mappable |
|
|
|
map << map_before_actions! |
|
|
|
case mappable |
|
in Sequence |
|
map << map_members! |
|
in Member |
|
map << mappable.action.inspect |
|
end |
|
|
|
map << map_after_actions! |
|
|
|
@map = map.flatten |
|
end |
|
|
|
def map_before_actions! |
|
mappable.before_actions.map do |action| |
|
handle_action_map(action) |
|
end |
|
end |
|
|
|
def map_members! |
|
mappable.members.map do |member| |
|
handle_action_map(member) |
|
end |
|
end |
|
|
|
def map_after_actions! |
|
mappable.after_actions.map do |action| |
|
handle_action_map(action) |
|
end |
|
end |
|
|
|
def to_a |
|
@map |
|
end |
|
|
|
private |
|
|
|
def handle_action_map(action) |
|
case action |
|
in LightService::Action | Proc |
|
return action.inspect |
|
in Member |
|
return action.flatten |
|
in Sequence |
|
return action.with(mappable.context).flatten |
|
end |
|
end |
|
end |
|
|
|
as = Sequence[ |
|
Sequence[Action1, Action2].before(Action11).after(Action12), |
|
Member.new(Action3).after( |
|
->(ctx) { p 'Into a proc mutating the context' and ctx[:bar] = :baz } |
|
), |
|
Action4 |
|
] |
|
.after_each([Action7, Action8]) |
|
.before_each(Action5, Action6) |
|
.before(Action9) |
|
.after(Action10) |
|
.with({ foo: [] }) |
|
|
|
pp as |
|
pp as.flatten |
|
outcome = as.call |
|
p outcome |
|
|
|
# The STDOUT |
|
# |
|
# #<Sequence:0x000000011805d368 |
|
# @after_actions=[Action10], |
|
# @before_actions=[Action9], |
|
# @context={:foo=>[]}, |
|
# @members= |
|
# [ |
|
# #<Sequence:0x000000011805dac0 @after_actions=[Action12, Action7, Action8], @before_actions=[Action11, Action5, Action6], |
|
# @members=[ |
|
# #<Member:0x000000011805d8b8 @action=Action1, @after_actions=[], @before_actions=[]>, |
|
# #<Member:0x000000011805d7f0 @action=Action2, @after_actions=[], @before_actions=[]> |
|
# ]>, |
|
# #<Member:0x000000011805d548 @action=Action3, @after_actions=[#<Proc:0x000000011805d4d0 main.rb:299 (lambda)>, Action7, Action8], @before_actions=[Action5, Action6]>, |
|
# #<Member:0x000000011805d228 @action=Action4, @after_actions=[Action7, Action8], @before_actions=[Action5, Action6]> |
|
# ] |
|
# > |
|
# |
|
# ["Action9", "Action11", "Action5", "Action6", "Action1", "Action2", "Action12", "Action7", "Action8", "Action5", "Action6", "Action3", "#<Proc:0x000000011805d4d0 main.rb:299 (lambda)>", "Action7", "Action8", "Action5", "Action6", "Action4", "Action7", "Action8", "Action10"] |
|
# |
|
# "Action -Action9- called. Context: {:foo=>[\"Action9\"]}" |
|
# "Action -Action11- called. Context: {:foo=>[\"Action9\", \"Action11\"]}" |
|
# "Action -Action5- called. Context: {:foo=>[\"Action9\", \"Action11\", \"Action5\"]}" |
|
# "Action -Action6- called. Context: {:foo=>[\"Action9\", \"Action11\", \"Action5\", \"Action6\"]}" |
|
# "Action -Action1- called. Context: {:foo=>[\"Action9\", \"Action11\", \"Action5\", \"Action6\", \"Action1\"]}" |
|
# "Action -Action2- called. Context: {:foo=>[\"Action9\", \"Action11\", \"Action5\", \"Action6\", \"Action1\", \"Action2\"]}" |
|
# "Action -Action12- called. Context: {:foo=>[\"Action9\", \"Action11\", \"Action5\", \"Action6\", \"Action1\", \"Action2\", \"Action12\"]}" |
|
# "Action -Action7- called. Context: {:foo=>[\"Action9\", \"Action11\", \"Action5\", \"Action6\", \"Action1\", \"Action2\", \"Action12\", \"Action7\"]}" |
|
# "Action -Action8- called. Context: {:foo=>[\"Action9\", \"Action11\", \"Action5\", \"Action6\", \"Action1\", \"Action2\", \"Action12\", \"Action7\", \"Action8\"]}" |
|
# "Action -Action5- called. Context: {:foo=>[\"Action9\", \"Action11\", \"Action5\", \"Action6\", \"Action1\", \"Action2\", \"Action12\", \"Action7\", \"Action8\", \"Action5\"]}" |
|
# "Action -Action6- called. Context: {:foo=>[\"Action9\", \"Action11\", \"Action5\", \"Action6\", \"Action1\", \"Action2\", \"Action12\", \"Action7\", \"Action8\", \"Action5\", \"Action6\"]}" |
|
# "Action -Action3- called. Context: {:foo=>[\"Action9\", \"Action11\", \"Action5\", \"Action6\", \"Action1\", \"Action2\", \"Action12\", \"Action7\", \"Action8\", \"Action5\", \"Action6\", \"Action3\"]}" |
|
# "Into a proc mutating the context" |
|
# "Action -Action7- called. Context: {:foo=>[\"Action9\", \"Action11\", \"Action5\", \"Action6\", \"Action1\", \"Action2\", \"Action12\", \"Action7\", \"Action8\", \"Action5\", \"Action6\", \"Action3\", \"Action7\"], :bar=>:baz}" |
|
# "Action -Action8- called. Context: {:foo=>[\"Action9\", \"Action11\", \"Action5\", \"Action6\", \"Action1\", \"Action2\", \"Action12\", \"Action7\", \"Action8\", \"Action5\", \"Action6\", \"Action3\", \"Action7\", \"Action8\"], :bar=>:baz}" |
|
# "Action -Action5- called. Context: {:foo=>[\"Action9\", \"Action11\", \"Action5\", \"Action6\", \"Action1\", \"Action2\", \"Action12\", \"Action7\", \"Action8\", \"Action5\", \"Action6\", \"Action3\", \"Action7\", \"Action8\", \"Action5\"], :bar=>:baz}" |
|
# "Action -Action6- called. Context: {:foo=>[\"Action9\", \"Action11\", \"Action5\", \"Action6\", \"Action1\", \"Action2\", \"Action12\", \"Action7\", \"Action8\", \"Action5\", \"Action6\", \"Action3\", \"Action7\", \"Action8\", \"Action5\", \"Action6\"], :bar=>:baz}" |
|
# "Action -Action4- called. Context: {:foo=>[\"Action9\", \"Action11\", \"Action5\", \"Action6\", \"Action1\", \"Action2\", \"Action12\", \"Action7\", \"Action8\", \"Action5\", \"Action6\", \"Action3\", \"Action7\", \"Action8\", \"Action5\", \"Action6\", \"Action4\"], :bar=>:baz}" |
|
# "Action -Action7- called. Context: {:foo=>[\"Action9\", \"Action11\", \"Action5\", \"Action6\", \"Action1\", \"Action2\", \"Action12\", \"Action7\", \"Action8\", \"Action5\", \"Action6\", \"Action3\", \"Action7\", \"Action8\", \"Action5\", \"Action6\", \"Action4\", \"Action7\"], :bar=>:baz}" |
|
# "Action -Action8- called. Context: {:foo=>[\"Action9\", \"Action11\", \"Action5\", \"Action6\", \"Action1\", \"Action2\", \"Action12\", \"Action7\", \"Action8\", \"Action5\", \"Action6\", \"Action3\", \"Action7\", \"Action8\", \"Action5\", \"Action6\", \"Action4\", \"Action7\", \"Action8\"], :bar=>:baz}" |
|
# "Action -Action10- called. Context: {:foo=>[\"Action9\", \"Action11\", \"Action5\", \"Action6\", \"Action1\", \"Action2\", \"Action12\", \"Action7\", \"Action8\", \"Action5\", \"Action6\", \"Action3\", \"Action7\", \"Action8\", \"Action5\", \"Action6\", \"Action4\", \"Action7\", \"Action8\", \"Action10\"], :bar=>:baz}" |
|
# |
|
# LightService::Context({:foo=>["Action9", "Action11", "Action5", "Action6", "Action1", "Action2", "Action12", "Action7", "Action8", "Action5", "Action6", "Action3", "Action7", "Action8", "Action5", "Action6", "Action4", "Action7", "Action8", "Action10"], :bar=>:baz}, success: true, message: '', error_code: nil, skip_remaining: false, aliases: {}) |