railway-rb 0.0.1
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/lib/railway.rb +121 -0
- metadata +43 -0
checksums.yaml
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
---
|
|
2
|
+
SHA256:
|
|
3
|
+
metadata.gz: 8698c98d0e081c760f0c652d7875bf1ad9050f36989de032187156e68c6c6a90
|
|
4
|
+
data.tar.gz: 79a12dd5fd91fb69afb56e10f737939659ea2a5937f3abc83debc8c9d5cc380c
|
|
5
|
+
SHA512:
|
|
6
|
+
metadata.gz: 859724aff46f8909025681cb3a48eb01b5f7543c5ec00ec736ac6aa07ed4709fe732e205e869a0e837bb828dbebf4c3e4aece4d0433b348f934cbe9328a41dd1
|
|
7
|
+
data.tar.gz: 6b2dd0ca7b4e48e692dd324958905818b53e22879dbbbea39ed6ebff8c0f9178af38af8dc06dffae239c9180541e284f887de28d5778933f2a3c6ad61073bbe2
|
data/lib/railway.rb
ADDED
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# Include this module to enable Railway syntactic expression.
|
|
4
|
+
# Example:
|
|
5
|
+
#
|
|
6
|
+
# class Lorem
|
|
7
|
+
# include Railway
|
|
8
|
+
#
|
|
9
|
+
# def greeting(person)
|
|
10
|
+
# with { person }.as var(:pax).when { pax.is_a? String }
|
|
11
|
+
# .then { "Hello, #{pax}" }.as var(:message) do
|
|
12
|
+
# pp message
|
|
13
|
+
# end.run
|
|
14
|
+
# end
|
|
15
|
+
# end
|
|
16
|
+
#
|
|
17
|
+
module Railway
|
|
18
|
+
def var(sym, setter: nil)
|
|
19
|
+
block = BuildingBlock.new(name: sym, setter_name: setter)
|
|
20
|
+
Builder.new(block)
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
def with(&assign_block)
|
|
24
|
+
block = BuildingBlock.new(assign_block: assign_block)
|
|
25
|
+
Builder.new(block, self)
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
BuildingBlock = Struct.new(
|
|
29
|
+
:name, :setter_name, :assign_block, :guard_block, :extra_blocks,
|
|
30
|
+
keyword_init: true
|
|
31
|
+
)
|
|
32
|
+
|
|
33
|
+
# This class is used to combine and execute building block properly
|
|
34
|
+
#
|
|
35
|
+
class Builder
|
|
36
|
+
attr_reader :blocks
|
|
37
|
+
|
|
38
|
+
def initialize(starting_block, ctx = nil)
|
|
39
|
+
@blocks = [starting_block]
|
|
40
|
+
@context = ctx
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
def when(&block)
|
|
44
|
+
blocks.first.guard_block = block
|
|
45
|
+
self
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
def then(&block)
|
|
49
|
+
blocks.last.extra_blocks = [*blocks.last.extra_blocks, next_assign_block] if next_assign_block
|
|
50
|
+
|
|
51
|
+
@next_assign_block = block
|
|
52
|
+
self
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
def as(next_builder, &block) # rubocop:disable Metrics/MethodLength
|
|
56
|
+
if block
|
|
57
|
+
@accept_block = block
|
|
58
|
+
assign_block = blocks.first.assign_block
|
|
59
|
+
@blocks = next_builder.blocks.clone
|
|
60
|
+
blocks.first.assign_block = assign_block
|
|
61
|
+
else
|
|
62
|
+
next_blocks = next_builder.blocks.clone
|
|
63
|
+
next_blocks.first.assign_block = next_assign_block
|
|
64
|
+
@blocks += next_blocks
|
|
65
|
+
@next_assign_block = nil
|
|
66
|
+
end
|
|
67
|
+
self
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
def otherwise(&block)
|
|
71
|
+
@reject_block = block if block
|
|
72
|
+
self
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
def run
|
|
76
|
+
@result = Struct.new(*blocks.map(&:name)).new
|
|
77
|
+
|
|
78
|
+
blocks.each do |block|
|
|
79
|
+
apply_block(block)
|
|
80
|
+
return reject(block) unless continue_block?(block)
|
|
81
|
+
|
|
82
|
+
[*block.extra_blocks].each { |b| instance_exec(&b) }
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
instance_exec(&accept_block)
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
private
|
|
89
|
+
|
|
90
|
+
attr_reader :context, :next_assign_block, :result, :accept_block, :reject_block
|
|
91
|
+
|
|
92
|
+
def apply_block(block)
|
|
93
|
+
sym = block.name
|
|
94
|
+
result[sym] = instance_exec(&block.assign_block)
|
|
95
|
+
return if !context || !block.setter_name
|
|
96
|
+
|
|
97
|
+
context.instance_variable_set("@#{block.setter_name}".to_sym, result[sym])
|
|
98
|
+
end
|
|
99
|
+
|
|
100
|
+
def continue_block?(block)
|
|
101
|
+
!block.guard_block || instance_exec(&block.guard_block)
|
|
102
|
+
end
|
|
103
|
+
|
|
104
|
+
def reject(block)
|
|
105
|
+
sym = block.name
|
|
106
|
+
reject_block && instance_exec(sym, result[sym], &reject_block)
|
|
107
|
+
end
|
|
108
|
+
|
|
109
|
+
def method_missing(a_method, *args, &block)
|
|
110
|
+
return result[a_method] if result&.members&.include?(a_method)
|
|
111
|
+
|
|
112
|
+
return context.send(a_method, *args, &block) if context.respond_to?(a_method, true)
|
|
113
|
+
|
|
114
|
+
super(a_method, *args, &block)
|
|
115
|
+
end
|
|
116
|
+
|
|
117
|
+
def respond_to_missing?(a_method, *)
|
|
118
|
+
result&.members&.include?(a_method) || context.respond_to?(a_method)
|
|
119
|
+
end
|
|
120
|
+
end
|
|
121
|
+
end
|
metadata
ADDED
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
|
2
|
+
name: railway-rb
|
|
3
|
+
version: !ruby/object:Gem::Version
|
|
4
|
+
version: 0.0.1
|
|
5
|
+
platform: ruby
|
|
6
|
+
authors:
|
|
7
|
+
- Hoan Nguyen
|
|
8
|
+
autorequire:
|
|
9
|
+
bindir: bin
|
|
10
|
+
cert_chain: []
|
|
11
|
+
date: 2020-12-25 00:00:00.000000000 Z
|
|
12
|
+
dependencies: []
|
|
13
|
+
description: A functional approach to error handling. Inspired by Elixir `with` statement.
|
|
14
|
+
email: hoan006@gmail.com
|
|
15
|
+
executables: []
|
|
16
|
+
extensions: []
|
|
17
|
+
extra_rdoc_files: []
|
|
18
|
+
files:
|
|
19
|
+
- lib/railway.rb
|
|
20
|
+
homepage: http://github.com/hoan006
|
|
21
|
+
licenses:
|
|
22
|
+
- MIT
|
|
23
|
+
metadata: {}
|
|
24
|
+
post_install_message:
|
|
25
|
+
rdoc_options: []
|
|
26
|
+
require_paths:
|
|
27
|
+
- lib
|
|
28
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
|
29
|
+
requirements:
|
|
30
|
+
- - "~>"
|
|
31
|
+
- !ruby/object:Gem::Version
|
|
32
|
+
version: '2.4'
|
|
33
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
34
|
+
requirements:
|
|
35
|
+
- - ">="
|
|
36
|
+
- !ruby/object:Gem::Version
|
|
37
|
+
version: '0'
|
|
38
|
+
requirements: []
|
|
39
|
+
rubygems_version: 3.1.2
|
|
40
|
+
signing_key:
|
|
41
|
+
specification_version: 4
|
|
42
|
+
summary: Railway-Oriented Programming!
|
|
43
|
+
test_files: []
|