grumlin 0.19.7 → 0.20.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.rspec +1 -0
- data/Gemfile +1 -0
- data/Gemfile.lock +3 -1
- data/README.md +31 -0
- data/bin/console +2 -0
- data/gremlin_server/Dockerfile +2 -0
- data/lib/grumlin/action.rb +7 -38
- data/lib/grumlin/repository/instance_methods.rb +5 -5
- data/lib/grumlin/repository.rb +14 -6
- data/lib/grumlin/request_dispatcher.rb +2 -2
- data/lib/grumlin/shortcut.rb +6 -1
- data/lib/grumlin/shortcuts/storage.rb +105 -0
- data/lib/grumlin/shortcuts/upserts.rb +3 -3
- data/lib/grumlin/shortcuts.rb +9 -16
- data/lib/grumlin/shortcuts_applyer.rb +15 -17
- data/lib/grumlin/steppable.rb +32 -0
- data/lib/grumlin/steps.rb +2 -2
- data/lib/grumlin/sugar.rb +4 -6
- data/lib/grumlin/traversal_start.rb +1 -39
- data/lib/grumlin/version.rb +1 -1
- metadata +4 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 0ab9e228cb2cd8ecc761136dab0e92a42aae268708aecf5784aac670a4404ecb
|
4
|
+
data.tar.gz: 984d2323e97056291370c37dadc2cf90d694f27caa753053a110165985dc067b
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 27a73c8e77850b99e030c129f8df2e30fc6933ad4da29e5a205b7812c64c88f24d7aceb2128af6687fc4bf35056509421989d2cae5a51c5db6f53c18f735fe97
|
7
|
+
data.tar.gz: adf371f27c60f2c0e70feaafcfede32dc64beef09b098bf35f01270b37049ee5ce76a68c184bf80abe33c7069ca8b947bbd54ecdcab42fd461a8bb09c270b1b1
|
data/.rspec
CHANGED
data/Gemfile
CHANGED
data/Gemfile.lock
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
grumlin (0.
|
4
|
+
grumlin (0.20.0)
|
5
5
|
async-pool (~> 0.3)
|
6
6
|
async-websocket (~> 0.19)
|
7
7
|
oj (~> 3.13)
|
@@ -48,6 +48,7 @@ GEM
|
|
48
48
|
concurrent-ruby (1.1.10)
|
49
49
|
console (1.15.3)
|
50
50
|
fiber-local
|
51
|
+
dead_end (4.0.0)
|
51
52
|
diff-lcs (1.5.0)
|
52
53
|
docile (1.4.0)
|
53
54
|
e2mmap (0.1.0)
|
@@ -172,6 +173,7 @@ PLATFORMS
|
|
172
173
|
DEPENDENCIES
|
173
174
|
async-rspec
|
174
175
|
benchmark-ips
|
176
|
+
dead_end
|
175
177
|
factory_bot
|
176
178
|
grumlin!
|
177
179
|
memory_profiler
|
data/README.md
CHANGED
@@ -143,6 +143,20 @@ class MyRepository
|
|
143
143
|
end
|
144
144
|
```
|
145
145
|
|
146
|
+
##### Overriding standard steps
|
147
|
+
|
148
|
+
Sometimes it may be useful to override standard steps. Grumlin does not allow it by default, but one
|
149
|
+
is still able to override standard steps if they know what they are doing:
|
150
|
+
|
151
|
+
```ruby
|
152
|
+
shortcut :addV, override: true do |label|
|
153
|
+
super(label).property(:default, :value)
|
154
|
+
end
|
155
|
+
```
|
156
|
+
|
157
|
+
This will create a new shortcut that overrides the standard step `addV` and adds default properties to all vertices
|
158
|
+
created by the repository that uses this shortcut.
|
159
|
+
|
146
160
|
#### Grumlin::Repository
|
147
161
|
`Grumlin::Repository` combines functionality of `Grumlin::Sugar` and `Grumlin::Shortcuts` as well as adds a few useful
|
148
162
|
shortcuts to make gremlin code more rubyish. Can be used as a drop in replacement for `Grumlin::Sugar`. Remember that
|
@@ -167,6 +181,23 @@ class MyRepository
|
|
167
181
|
hasAll(T.label => :triangle, color: color)
|
168
182
|
end
|
169
183
|
|
184
|
+
# `default_vertex_properties` and `default_edge_properties`
|
185
|
+
# override `addV` and `addE` according and inject hashes returned from passed
|
186
|
+
# as properties for newly created vertices and edges.
|
187
|
+
# In case if a repository is inherited, newly defined default properties will be merged to
|
188
|
+
# default properties defined in the parent repository.
|
189
|
+
default_vertex_properties do |_label|
|
190
|
+
{
|
191
|
+
created_at: Time.now.to_i
|
192
|
+
}
|
193
|
+
end
|
194
|
+
|
195
|
+
default_edge_properties do |_label|
|
196
|
+
{
|
197
|
+
created_at: Time.now.to_i
|
198
|
+
}
|
199
|
+
end
|
200
|
+
|
170
201
|
# g and __ are already aware of shortcuts
|
171
202
|
query(:triangles_with_color, return_mode: :list) do |color| # :list is the default return mode, also possible: :none, :single, :traversal
|
172
203
|
g.V.hasLabel(:triangle)
|
data/bin/console
CHANGED
data/gremlin_server/Dockerfile
CHANGED
data/lib/grumlin/action.rb
CHANGED
@@ -1,32 +1,17 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
module Grumlin
|
4
|
-
class Action
|
5
|
-
|
6
|
-
CONFIGURATION_STEPS = Grumlin.definitions.dig(:steps, :configuration).map(&:to_sym).freeze
|
7
|
-
REGULAR_STEPS = Grumlin.definitions.dig(:steps, :regular).map(&:to_sym).freeze
|
4
|
+
class Action < Steppable
|
5
|
+
attr_reader :name, :args, :params, :next_step, :configuration_steps, :previous_step, :shortcut
|
8
6
|
|
9
|
-
|
10
|
-
|
11
|
-
attr_reader :name, :args, :params, :shortcuts, :next_step, :configuration_steps, :previous_step
|
12
|
-
|
13
|
-
def initialize(name, args: [], params: {}, previous_step: nil, shortcuts: {}, pool: Grumlin.default_pool)
|
7
|
+
def initialize(name, args: [], params: {}, previous_step: nil, pool: nil)
|
8
|
+
super()
|
14
9
|
@name = name.to_sym
|
15
10
|
@args = args # TODO: add recursive validation: only json types or Action
|
16
11
|
@params = params # TODO: add recursive validation: only json types
|
17
12
|
@previous_step = previous_step
|
18
|
-
@
|
19
|
-
@pool = pool
|
20
|
-
end
|
21
|
-
|
22
|
-
ALL_STEPS.each do |step|
|
23
|
-
define_method step do |*args, **params|
|
24
|
-
step(step, *args, **params)
|
25
|
-
end
|
26
|
-
end
|
27
|
-
|
28
|
-
def step(name, *args, **params)
|
29
|
-
Action.new(name, args: args, params: params, previous_step: self, shortcuts: @shortcuts, pool: @pool)
|
13
|
+
@shortcut = shortcuts[@name]
|
14
|
+
@pool = pool || Grumlin.default_pool
|
30
15
|
end
|
31
16
|
|
32
17
|
def configuration_step?
|
@@ -45,23 +30,13 @@ module Grumlin
|
|
45
30
|
ALL_STEPS.include?(@name)
|
46
31
|
end
|
47
32
|
|
48
|
-
def shortcut?
|
49
|
-
@shortcuts.key?(@name)
|
50
|
-
end
|
51
|
-
|
52
|
-
def method_missing(name, *args, **params)
|
53
|
-
return step(name, *args, **params) if @shortcuts.key?(name)
|
54
|
-
|
55
|
-
super
|
56
|
-
end
|
57
|
-
|
58
33
|
def ==(other)
|
59
34
|
self.class == other.class &&
|
60
35
|
@name == other.name &&
|
61
36
|
@args == other.args &&
|
62
37
|
@params == other.params &&
|
63
38
|
@previous_step == other.previous_step &&
|
64
|
-
|
39
|
+
shortcuts == other.shortcuts
|
65
40
|
end
|
66
41
|
|
67
42
|
def steps
|
@@ -108,11 +83,5 @@ module Grumlin
|
|
108
83
|
client.write(bytecode(no_return: true))
|
109
84
|
end
|
110
85
|
end
|
111
|
-
|
112
|
-
private
|
113
|
-
|
114
|
-
def respond_to_missing?(name, _include_private = false)
|
115
|
-
@shortcuts.key?(name)
|
116
|
-
end
|
117
86
|
end
|
118
87
|
end
|
@@ -5,6 +5,8 @@ module Grumlin
|
|
5
5
|
module InstanceMethods
|
6
6
|
include Grumlin::Expressions
|
7
7
|
|
8
|
+
extend Forwardable
|
9
|
+
|
8
10
|
UPSERT_RETRY_PARAMS = {
|
9
11
|
on: [Grumlin::AlreadyExistsError, Grumlin::ConcurrentInsertFailedError],
|
10
12
|
sleep_method: ->(n) { Async::Task.current.sleep(n) },
|
@@ -14,12 +16,10 @@ module Grumlin
|
|
14
16
|
|
15
17
|
DEFAULT_ERROR_HANDLING_STRATEGY = ErrorHandlingStrategy.new(mode: :retry, **UPSERT_RETRY_PARAMS)
|
16
18
|
|
17
|
-
|
18
|
-
@__ ||= TraversalStart.new(self.class.shortcuts)
|
19
|
-
end
|
19
|
+
def_delegators :shortcuts, :g, :__
|
20
20
|
|
21
|
-
def
|
22
|
-
|
21
|
+
def shortcuts
|
22
|
+
self.class.shortcuts
|
23
23
|
end
|
24
24
|
|
25
25
|
def drop_vertex(id)
|
data/lib/grumlin/repository.rb
CHANGED
@@ -23,7 +23,7 @@ module Grumlin
|
|
23
23
|
|
24
24
|
define_method name do |*args, query_params: {}, **params, &block|
|
25
25
|
t = instance_exec(*args, **params, &query_block)
|
26
|
-
return t if
|
26
|
+
return t if t.nil? || (t.respond_to?(:empty?) && t.empty?)
|
27
27
|
|
28
28
|
unless t.is_a?(Grumlin::Action)
|
29
29
|
raise WrongQueryResult,
|
@@ -45,8 +45,20 @@ module Grumlin
|
|
45
45
|
end
|
46
46
|
end
|
47
47
|
|
48
|
+
def default_vertex_properties(&block)
|
49
|
+
shortcut :addV, override: true do |*args|
|
50
|
+
super(*args).props(**block.call(*args)) # rubocop:disable Performance/RedundantBlockCall
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
def default_edge_properties(&block)
|
55
|
+
shortcut :addE, override: true do |*args|
|
56
|
+
super(*args).props(**block.call(*args)) # rubocop:disable Performance/RedundantBlockCall
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
48
60
|
def validate_return_mode!(return_mode)
|
49
|
-
return return_mode if RETURN_MODES.
|
61
|
+
return return_mode if RETURN_MODES.include?(return_mode)
|
50
62
|
|
51
63
|
raise ArgumentError, "unsupported return mode #{return_mode}. Supported modes: #{RETURN_MODES.keys}"
|
52
64
|
end
|
@@ -60,9 +72,5 @@ module Grumlin
|
|
60
72
|
raise ArgumentError,
|
61
73
|
"postprocess_with must be a String, Symbol or a callable object, given: #{postprocess_with.class}"
|
62
74
|
end
|
63
|
-
|
64
|
-
def empty_result?(result)
|
65
|
-
result.nil? || (result.respond_to?(:empty?) && result.empty?)
|
66
|
-
end
|
67
75
|
end
|
68
76
|
end
|
@@ -38,7 +38,7 @@ module Grumlin
|
|
38
38
|
end
|
39
39
|
|
40
40
|
def add_request(request)
|
41
|
-
raise RequestAlreadyAddedError if @requests.
|
41
|
+
raise RequestAlreadyAddedError if @requests.include?(request[:requestId])
|
42
42
|
|
43
43
|
Async::Channel.new.tap do |channel|
|
44
44
|
@requests[request[:requestId]] = { request: request, result: [], channel: channel }
|
@@ -73,7 +73,7 @@ module Grumlin
|
|
73
73
|
end
|
74
74
|
|
75
75
|
def ongoing_request?(request_id)
|
76
|
-
@requests.
|
76
|
+
@requests.include?(request_id)
|
77
77
|
end
|
78
78
|
|
79
79
|
def clear
|
data/lib/grumlin/shortcut.rb
CHANGED
@@ -9,8 +9,9 @@ module Grumlin
|
|
9
9
|
def_delegator :@block, :arity
|
10
10
|
def_delegator :@block, :source_location
|
11
11
|
|
12
|
-
def initialize(name, &block)
|
12
|
+
def initialize(name, lazy: true, &block)
|
13
13
|
@name = name
|
14
|
+
@lazy = lazy
|
14
15
|
@block = block
|
15
16
|
end
|
16
17
|
|
@@ -18,6 +19,10 @@ module Grumlin
|
|
18
19
|
@name == other.name && @block == other.block
|
19
20
|
end
|
20
21
|
|
22
|
+
def lazy?
|
23
|
+
@lazy
|
24
|
+
end
|
25
|
+
|
21
26
|
# TODO: to_s, inspect, preview
|
22
27
|
|
23
28
|
def apply(object, *args, **params)
|
@@ -0,0 +1,105 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Grumlin
|
4
|
+
module Shortcuts
|
5
|
+
class Storage
|
6
|
+
extend Forwardable
|
7
|
+
|
8
|
+
class << self
|
9
|
+
def [](other)
|
10
|
+
new(other)
|
11
|
+
end
|
12
|
+
|
13
|
+
def empty
|
14
|
+
@empty ||= new
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
def initialize(storage = {})
|
19
|
+
@storage = storage
|
20
|
+
storage.each do |n, s|
|
21
|
+
add(n, s)
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
def_delegator :@storage, :[]
|
26
|
+
def_delegator :@storage, :include?, :known?
|
27
|
+
def_delegator :@storage, :keys, :names
|
28
|
+
|
29
|
+
def ==(other)
|
30
|
+
@storage == other.storage
|
31
|
+
end
|
32
|
+
|
33
|
+
def add(name, shortcut)
|
34
|
+
# not lazy shortcuts are allowed to be overridden
|
35
|
+
if known?(name) && @storage[name] != shortcut && shortcut.lazy?
|
36
|
+
raise ArgumentError,
|
37
|
+
"shortcut '#{name}' already exists"
|
38
|
+
end
|
39
|
+
|
40
|
+
@storage[name] = shortcut
|
41
|
+
|
42
|
+
ac = action_class
|
43
|
+
|
44
|
+
shortcut_methods_module.define_method(name) do |*args, **params|
|
45
|
+
next ac.new(name, args: args, params: params, previous_step: self)
|
46
|
+
end
|
47
|
+
extend_traversal_classes(shortcut) unless shortcut.lazy?
|
48
|
+
end
|
49
|
+
|
50
|
+
def add_from(other)
|
51
|
+
other.storage.each do |name, shortcut|
|
52
|
+
add(name, shortcut)
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
def g
|
57
|
+
__
|
58
|
+
end
|
59
|
+
|
60
|
+
def __
|
61
|
+
@__ ||= traversal_start_class.new
|
62
|
+
end
|
63
|
+
|
64
|
+
def traversal_start_class
|
65
|
+
@traversal_start_class ||= shortcut_aware_class(TraversalStart)
|
66
|
+
end
|
67
|
+
|
68
|
+
def action_class
|
69
|
+
@action_class ||= shortcut_aware_class(Action)
|
70
|
+
end
|
71
|
+
|
72
|
+
protected
|
73
|
+
|
74
|
+
attr_reader :storage
|
75
|
+
|
76
|
+
private
|
77
|
+
|
78
|
+
def shortcut_methods_module
|
79
|
+
@shortcut_methods_module ||= begin
|
80
|
+
shorts = self
|
81
|
+
Module.new do
|
82
|
+
define_method :shortcuts do
|
83
|
+
shorts
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
def shortcut_aware_class(base)
|
90
|
+
methods = shortcut_methods_module
|
91
|
+
Class.new(base) do
|
92
|
+
include methods
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
def extend_traversal_classes(shortcut)
|
97
|
+
m = Module.new do
|
98
|
+
define_method(shortcut.name, &shortcut.block)
|
99
|
+
end
|
100
|
+
action_class.include(m)
|
101
|
+
traversal_start_class.include(m)
|
102
|
+
end
|
103
|
+
end
|
104
|
+
end
|
105
|
+
end
|
@@ -5,16 +5,16 @@ module Grumlin
|
|
5
5
|
module Upserts
|
6
6
|
extend Grumlin::Shortcuts
|
7
7
|
|
8
|
-
shortcut :upsertV do |label, id, create_properties, update_properties|
|
8
|
+
shortcut :upsertV do |label, id, create_properties = {}, update_properties = {}|
|
9
9
|
self.V(id)
|
10
10
|
.fold
|
11
|
-
.coalesce(
|
11
|
+
.coalesce(
|
12
12
|
__.unfold,
|
13
13
|
__.addV(label).props(**create_properties.merge(T.id => id))
|
14
14
|
).props(**update_properties)
|
15
15
|
end
|
16
16
|
|
17
|
-
shortcut :upsertE do |label, from, to, create_properties, update_properties|
|
17
|
+
shortcut :upsertE do |label, from, to, create_properties = {}, update_properties = {}|
|
18
18
|
self.V(from)
|
19
19
|
.outE(label).where(__.inV.hasId(to))
|
20
20
|
.fold
|
data/lib/grumlin/shortcuts.rb
CHANGED
@@ -11,33 +11,26 @@ module Grumlin
|
|
11
11
|
subclass.shortcuts_from(self)
|
12
12
|
end
|
13
13
|
|
14
|
-
def shortcut(name, shortcut = nil,
|
14
|
+
def shortcut(name, shortcut = nil, override: false, lazy: true, &block)
|
15
15
|
name = name.to_sym
|
16
|
-
|
17
|
-
if Grumlin::Action::REGULAR_STEPS.include?(name)
|
18
|
-
raise ArgumentError,
|
19
|
-
"cannot use names of standard gremlin steps"
|
20
|
-
end
|
16
|
+
lazy = false if override
|
21
17
|
|
22
|
-
if
|
23
|
-
raise ArgumentError,
|
18
|
+
if Grumlin::Action::REGULAR_STEPS.include?(name) && !override
|
19
|
+
raise ArgumentError,
|
20
|
+
"overriding standard gremlin steps is not allowed, if you know what you're doing, pass `override: true`"
|
24
21
|
end
|
25
22
|
|
26
|
-
shortcut
|
23
|
+
raise ArgumentError, "either shortcut or block must be passed" if [shortcut, block].count(&:nil?) != 1
|
27
24
|
|
28
|
-
|
29
|
-
|
30
|
-
shortcuts[name] = shortcut
|
25
|
+
shortcuts.add(name, shortcut || Shortcut.new(name, lazy: lazy, &block))
|
31
26
|
end
|
32
27
|
|
33
28
|
def shortcuts_from(other_shortcuts)
|
34
|
-
other_shortcuts.shortcuts
|
35
|
-
shortcut(name, shortcut)
|
36
|
-
end
|
29
|
+
shortcuts.add_from(other_shortcuts.shortcuts)
|
37
30
|
end
|
38
31
|
|
39
32
|
def shortcuts
|
40
|
-
@shortcuts ||=
|
33
|
+
@shortcuts ||= Storage.new
|
41
34
|
end
|
42
35
|
end
|
43
36
|
end
|
@@ -4,15 +4,17 @@ module Grumlin
|
|
4
4
|
class ShortcutsApplyer
|
5
5
|
class << self
|
6
6
|
def call(steps)
|
7
|
-
return steps
|
7
|
+
return steps if !steps.is_a?(Steps) || !steps.uses_shortcuts?
|
8
8
|
|
9
9
|
shortcuts = steps.shortcuts
|
10
10
|
|
11
|
-
|
12
|
-
|
11
|
+
steps = [
|
12
|
+
*process_steps(steps.configuration_steps, shortcuts),
|
13
|
+
*process_steps(steps.steps, shortcuts)
|
14
|
+
]
|
13
15
|
|
14
16
|
Steps.new(shortcuts).tap do |processed_steps|
|
15
|
-
|
17
|
+
steps.each do |step|
|
16
18
|
processed_steps.add(step.name, args: step.args, params: step.params)
|
17
19
|
end
|
18
20
|
end
|
@@ -22,21 +24,17 @@ module Grumlin
|
|
22
24
|
|
23
25
|
def process_steps(steps, shortcuts) # rubocop:disable Metrics/AbcSize
|
24
26
|
steps.each_with_object([]) do |step, result|
|
25
|
-
args = step.args.map
|
26
|
-
arg.is_a?(Steps) ? ShortcutsApplyer.call(arg) : arg
|
27
|
-
end
|
27
|
+
args = step.args.map { |arg| call(arg) }
|
28
28
|
|
29
|
-
|
30
|
-
|
31
|
-
action = shortcuts[step.name].apply(t, *args, **step.params)
|
32
|
-
next if action.nil? || action == t # Shortcut did not add any steps
|
29
|
+
shortcut = shortcuts[step.name]
|
30
|
+
next result << StepData.new(step.name, args: args, params: step.params) unless shortcut&.lazy?
|
33
31
|
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
32
|
+
t = shortcuts.__
|
33
|
+
action = shortcut.apply(t, *args, **step.params)
|
34
|
+
next if action.nil? || action == t # Shortcut did not add any steps
|
35
|
+
|
36
|
+
new_steps = call(Steps.from(action))
|
37
|
+
result.concat(new_steps.configuration_steps, new_steps.steps)
|
40
38
|
end
|
41
39
|
end
|
42
40
|
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Grumlin
|
4
|
+
class Steppable
|
5
|
+
extend Forwardable
|
6
|
+
|
7
|
+
START_STEPS = Grumlin.definitions.dig(:steps, :start).map(&:to_sym).freeze
|
8
|
+
REGULAR_STEPS = Grumlin.definitions.dig(:steps, :regular).map(&:to_sym).freeze
|
9
|
+
CONFIGURATION_STEPS = Grumlin.definitions.dig(:steps, :configuration).map(&:to_sym).freeze
|
10
|
+
|
11
|
+
ALL_STEPS = START_STEPS + CONFIGURATION_STEPS + REGULAR_STEPS
|
12
|
+
|
13
|
+
def initialize
|
14
|
+
return if respond_to?(:shortcuts)
|
15
|
+
|
16
|
+
raise RuntimerError,
|
17
|
+
"steppable must not be initialized directly, use Grumlin::Shortcuts::Storage#g or #__ instead"
|
18
|
+
end
|
19
|
+
|
20
|
+
ALL_STEPS.each do |step|
|
21
|
+
define_method step do |*args, **params|
|
22
|
+
shortcuts.action_class.new(step, args: args, params: params, previous_step: self)
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
def step(name, *args, **params)
|
27
|
+
shortcuts.action_class.new(name, args: args, params: params, previous_step: self)
|
28
|
+
end
|
29
|
+
|
30
|
+
def_delegator :shortcuts, :__
|
31
|
+
end
|
32
|
+
end
|
data/lib/grumlin/steps.rb
CHANGED
@@ -11,7 +11,7 @@ module Grumlin
|
|
11
11
|
shortcuts = action.shortcuts
|
12
12
|
actions = []
|
13
13
|
|
14
|
-
until action.nil?
|
14
|
+
until action.nil? || action.is_a?(TraversalStart)
|
15
15
|
actions.unshift(action)
|
16
16
|
action = action.previous_step
|
17
17
|
end
|
@@ -56,7 +56,7 @@ module Grumlin
|
|
56
56
|
|
57
57
|
def shortcuts?(steps_ary)
|
58
58
|
steps_ary.any? do |step|
|
59
|
-
@shortcuts.
|
59
|
+
@shortcuts.known?(step.name) || step.args.any? do |arg|
|
60
60
|
arg.is_a?(Steps) ? arg.uses_shortcuts? : false
|
61
61
|
end
|
62
62
|
end
|
data/lib/grumlin/sugar.rb
CHANGED
@@ -6,12 +6,10 @@ module Grumlin
|
|
6
6
|
base.include(Grumlin::Expressions)
|
7
7
|
end
|
8
8
|
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
def g(shortcuts = {})
|
14
|
-
Grumlin::TraversalStart.new(shortcuts)
|
9
|
+
%i[__ g].each do |name|
|
10
|
+
define_method name do |cuts = Shortcuts::Storage.empty|
|
11
|
+
cuts.send(name)
|
12
|
+
end
|
15
13
|
end
|
16
14
|
end
|
17
15
|
end
|
@@ -1,39 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
module Grumlin
|
4
|
-
class TraversalStart
|
5
|
-
START_STEPS = Grumlin.definitions.dig(:steps, :start).map(&:to_sym).freeze
|
6
|
-
REGULAR_STEPS = Grumlin.definitions.dig(:steps, :regular).map(&:to_sym).freeze
|
7
|
-
CONFIGURATION_STEPS = Grumlin.definitions.dig(:steps, :configuration).map(&:to_sym).freeze
|
8
|
-
|
9
|
-
ALL_STEPS = START_STEPS + CONFIGURATION_STEPS + REGULAR_STEPS
|
10
|
-
|
11
|
-
ALL_STEPS.each do |step|
|
12
|
-
define_method step do |*args, **params|
|
13
|
-
step(step, *args, **params)
|
14
|
-
end
|
15
|
-
end
|
16
|
-
|
17
|
-
attr_reader :shortcuts
|
18
|
-
|
19
|
-
def initialize(shortcuts)
|
20
|
-
@shortcuts = shortcuts
|
21
|
-
end
|
22
|
-
|
23
|
-
def step(name, *args, **params)
|
24
|
-
Action.new(name, args: args, params: params, shortcuts: @shortcuts)
|
25
|
-
end
|
26
|
-
|
27
|
-
def method_missing(name, *args, **params)
|
28
|
-
return step(name, *args, **params) if @shortcuts.key?(name)
|
29
|
-
|
30
|
-
super
|
31
|
-
end
|
32
|
-
|
33
|
-
def __
|
34
|
-
@__ ||= TraversalStart.new(@shortcuts) # TODO: allow only regular and start steps
|
35
|
-
end
|
36
|
-
|
4
|
+
class TraversalStart < Steppable
|
37
5
|
def to_s(*)
|
38
6
|
self.class.to_s
|
39
7
|
end
|
@@ -41,11 +9,5 @@ module Grumlin
|
|
41
9
|
def inspect
|
42
10
|
self.class.inspect
|
43
11
|
end
|
44
|
-
|
45
|
-
private
|
46
|
-
|
47
|
-
def respond_to_missing?(name, _include_private = false)
|
48
|
-
@shortcuts.key?(name)
|
49
|
-
end
|
50
12
|
end
|
51
13
|
end
|
data/lib/grumlin/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: grumlin
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.20.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Gleb Sinyavskiy
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2022-07-
|
11
|
+
date: 2022-07-14 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: async-pool
|
@@ -138,9 +138,11 @@ files:
|
|
138
138
|
- lib/grumlin/shortcut.rb
|
139
139
|
- lib/grumlin/shortcuts.rb
|
140
140
|
- lib/grumlin/shortcuts/properties.rb
|
141
|
+
- lib/grumlin/shortcuts/storage.rb
|
141
142
|
- lib/grumlin/shortcuts/upserts.rb
|
142
143
|
- lib/grumlin/shortcuts_applyer.rb
|
143
144
|
- lib/grumlin/step_data.rb
|
145
|
+
- lib/grumlin/steppable.rb
|
144
146
|
- lib/grumlin/steps.rb
|
145
147
|
- lib/grumlin/steps_serializers/bytecode.rb
|
146
148
|
- lib/grumlin/steps_serializers/human_readable_bytecode.rb
|