grumlin 0.23.0 → 1.0.0.rc2

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.
Files changed (79) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +9 -9
  3. data/Gemfile.lock +1 -1
  4. data/README.md +100 -142
  5. data/Rakefile +1 -1
  6. data/bin/console +18 -3
  7. data/doc/middlewares.md +49 -10
  8. data/lib/async/channel.rb +54 -56
  9. data/lib/grumlin/benchmark/repository.rb +10 -14
  10. data/lib/grumlin/client.rb +93 -95
  11. data/lib/grumlin/config.rb +33 -33
  12. data/lib/grumlin/dummy_transaction.rb +13 -15
  13. data/lib/grumlin/edge.rb +18 -20
  14. data/lib/grumlin/expressions/cardinality.rb +5 -9
  15. data/lib/grumlin/expressions/column.rb +5 -9
  16. data/lib/grumlin/expressions/expression.rb +7 -11
  17. data/lib/grumlin/expressions/operator.rb +5 -9
  18. data/lib/grumlin/expressions/order.rb +5 -9
  19. data/lib/grumlin/expressions/p.rb +27 -31
  20. data/lib/grumlin/expressions/pop.rb +5 -9
  21. data/lib/grumlin/expressions/scope.rb +5 -9
  22. data/lib/grumlin/expressions/t.rb +5 -9
  23. data/lib/grumlin/expressions/text_p.rb +5 -9
  24. data/lib/grumlin/expressions/with_options.rb +17 -21
  25. data/lib/grumlin/features/feature_list.rb +8 -12
  26. data/lib/grumlin/features/neptune_features.rb +5 -9
  27. data/lib/grumlin/features/tinkergraph_features.rb +5 -9
  28. data/lib/grumlin/features.rb +8 -10
  29. data/lib/grumlin/middlewares/apply_shortcuts.rb +4 -8
  30. data/lib/grumlin/middlewares/build_query.rb +16 -20
  31. data/lib/grumlin/middlewares/builder.rb +15 -0
  32. data/lib/grumlin/middlewares/cast_results.rb +3 -7
  33. data/lib/grumlin/middlewares/find_blocklisted_steps.rb +14 -0
  34. data/lib/grumlin/middlewares/find_mutating_steps.rb +9 -0
  35. data/lib/grumlin/middlewares/middleware.rb +6 -10
  36. data/lib/grumlin/middlewares/run_query.rb +3 -7
  37. data/lib/grumlin/middlewares/serialize_to_bytecode.rb +5 -9
  38. data/lib/grumlin/middlewares/serialize_to_steps.rb +4 -8
  39. data/lib/grumlin/path.rb +11 -13
  40. data/lib/grumlin/property.rb +14 -16
  41. data/lib/grumlin/query_validators/blocklisted_steps_validator.rb +22 -0
  42. data/lib/grumlin/query_validators/validator.rb +36 -0
  43. data/lib/grumlin/repository/error_handling_strategy.rb +36 -40
  44. data/lib/grumlin/repository/instance_methods.rb +115 -118
  45. data/lib/grumlin/repository.rb +82 -58
  46. data/lib/grumlin/request_dispatcher.rb +55 -57
  47. data/lib/grumlin/request_error_factory.rb +53 -55
  48. data/lib/grumlin/shortcut.rb +19 -21
  49. data/lib/grumlin/shortcuts/properties.rb +12 -16
  50. data/lib/grumlin/shortcuts/storage.rb +67 -74
  51. data/lib/grumlin/shortcuts/upserts.rb +19 -22
  52. data/lib/grumlin/shortcuts.rb +23 -25
  53. data/lib/grumlin/shortcuts_applyer.rb +27 -29
  54. data/lib/grumlin/step.rb +88 -90
  55. data/lib/grumlin/step_data.rb +12 -14
  56. data/lib/grumlin/steppable.rb +23 -25
  57. data/lib/grumlin/steps.rb +52 -54
  58. data/lib/grumlin/steps_serializers/bytecode.rb +53 -56
  59. data/lib/grumlin/steps_serializers/human_readable_bytecode.rb +17 -21
  60. data/lib/grumlin/steps_serializers/serializer.rb +7 -11
  61. data/lib/grumlin/steps_serializers/string.rb +26 -30
  62. data/lib/grumlin/test/rspec/db_cleaner_context.rb +8 -12
  63. data/lib/grumlin/test/rspec/gremlin_context.rb +18 -16
  64. data/lib/grumlin/test/rspec.rb +1 -5
  65. data/lib/grumlin/transaction.rb +34 -36
  66. data/lib/grumlin/transport.rb +71 -73
  67. data/lib/grumlin/traversal_start.rb +31 -33
  68. data/lib/grumlin/traversal_strategies/options_strategy.rb +3 -7
  69. data/lib/grumlin/traverser.rb +5 -7
  70. data/lib/grumlin/typed_value.rb +11 -13
  71. data/lib/grumlin/typing.rb +70 -72
  72. data/lib/grumlin/version.rb +1 -1
  73. data/lib/grumlin/vertex.rb +14 -16
  74. data/lib/grumlin/vertex_property.rb +14 -16
  75. data/lib/grumlin/with_extension.rb +17 -19
  76. data/lib/grumlin.rb +13 -0
  77. metadata +9 -6
  78. data/lib/grumlin/middlewares/frozen_builder.rb +0 -18
  79. data/lib/grumlin/sugar.rb +0 -15
@@ -1,125 +1,123 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- module Grumlin
4
- class Client
5
- class PoolResource < Async::Pool::Resource
6
- attr_reader :client
7
-
8
- def self.call
9
- config = Grumlin.config
10
- new(config.url, client_factory: config.client_factory, concurrency: config.client_concurrency)
11
- end
12
-
13
- def initialize(url, client_factory:, concurrency: 1, parent: Async::Task.current)
14
- super(concurrency)
15
- @client = client_factory.call(url, parent).tap(&:connect)
16
- @parent = parent
17
- end
3
+ class Grumlin::Client
4
+ class PoolResource < Async::Pool::Resource
5
+ attr_reader :client
18
6
 
19
- def closed?
20
- !@client.connected?
21
- end
7
+ def self.call
8
+ config = Grumlin.config
9
+ new(config.url, client_factory: config.client_factory, concurrency: config.client_concurrency)
10
+ end
22
11
 
23
- def close
24
- @client.close
25
- end
12
+ def initialize(url, client_factory:, concurrency: 1, parent: Async::Task.current)
13
+ super(concurrency)
14
+ @client = client_factory.call(url, parent).tap(&:connect)
15
+ @parent = parent
16
+ end
26
17
 
27
- def write(query)
28
- @client.write(query)
29
- ensure
30
- @count += 1
31
- end
18
+ def closed?
19
+ !@client.connected?
20
+ end
32
21
 
33
- def viable?
34
- !closed?
35
- end
22
+ def close
23
+ @client.close
24
+ end
36
25
 
37
- def reusable?
38
- !closed?
39
- end
26
+ def write(query)
27
+ @client.write(query)
28
+ ensure
29
+ @count += 1
40
30
  end
41
31
 
42
- include Console
32
+ def viable?
33
+ !closed?
34
+ end
43
35
 
44
- # Client is not reusable. Once closed should be recreated.
45
- def initialize(url, parent: Async::Task.current, **client_options)
46
- @url = url
47
- @client_options = client_options
48
- @parent = parent
49
- @request_dispatcher = nil
50
- @transport = nil
36
+ def reusable?
37
+ !closed?
51
38
  end
39
+ end
52
40
 
53
- def connect
54
- raise ClientClosedError if @closed
55
-
56
- @transport = build_transport
57
- response_channel = @transport.connect
58
- @request_dispatcher = RequestDispatcher.new
59
- @response_task = @parent.async do
60
- response_channel.each do |response|
61
- @request_dispatcher.add_response(response)
62
- end
63
- rescue Async::Stop, Async::TimeoutError, StandardError
64
- close(check_requests: false)
41
+ include Console
42
+
43
+ # Client is not reusable. Once closed should be recreated.
44
+ def initialize(url, parent: Async::Task.current, **client_options)
45
+ @url = url
46
+ @client_options = client_options
47
+ @parent = parent
48
+ @request_dispatcher = nil
49
+ @transport = nil
50
+ end
51
+
52
+ def connect
53
+ raise ClientClosedError if @closed
54
+
55
+ @transport = build_transport
56
+ response_channel = @transport.connect
57
+ @request_dispatcher = Grumlin::RequestDispatcher.new
58
+ @response_task = @parent.async do
59
+ response_channel.each do |response|
60
+ @request_dispatcher.add_response(response)
65
61
  end
66
- logger.debug(self, "Connected")
62
+ rescue Async::Stop, Async::TimeoutError, StandardError
63
+ close(check_requests: false)
67
64
  end
65
+ logger.debug(self, "Connected")
66
+ end
68
67
 
69
- # Before calling close the user must ensure that:
70
- # 1) There are no ongoing requests
71
- # 2) There will be no new writes after
72
- def close(check_requests: true) # rubocop:disable Metrics/CyclomaticComplexity,Metrics/PerceivedComplexity
73
- return if @closed
68
+ # Before calling close the user must ensure that:
69
+ # 1) There are no ongoing requests
70
+ # 2) There will be no new writes after
71
+ def close(check_requests: true) # rubocop:disable Metrics/CyclomaticComplexity,Metrics/PerceivedComplexity
72
+ return if @closed
74
73
 
75
- @closed = true
74
+ @closed = true
76
75
 
77
- @transport&.close
78
- @transport&.wait
76
+ @transport&.close
77
+ @transport&.wait
79
78
 
80
- @response_task&.stop
81
- @response_task&.wait
79
+ @response_task&.stop
80
+ @response_task&.wait
82
81
 
83
- return if @request_dispatcher&.requests&.empty?
82
+ return if @request_dispatcher&.requests&.empty?
84
83
 
85
- @request_dispatcher.clear unless check_requests
84
+ @request_dispatcher.clear unless check_requests
86
85
 
87
- raise ResourceLeakError, "Request list is not empty: #{@request_dispatcher.requests}" if check_requests
88
- ensure
89
- logger.debug(self, "Closed")
90
- end
86
+ raise ResourceLeakError, "Request list is not empty: #{@request_dispatcher.requests}" if check_requests
87
+ ensure
88
+ logger.debug(self, "Closed")
89
+ end
91
90
 
92
- def connected?
93
- @transport&.connected? || false
94
- end
91
+ def connected?
92
+ @transport&.connected? || false
93
+ end
95
94
 
96
- # TODO: support yielding
97
- def write(query)
98
- raise NotConnectedError unless connected?
99
-
100
- channel = @request_dispatcher.add_request(query)
101
- begin
102
- @transport.write(query)
103
- channel.dequeue
104
- rescue Async::Stop, Async::TimeoutError
105
- close(check_requests: false)
106
- raise
107
- end
95
+ # TODO: support yielding
96
+ def write(query)
97
+ raise NotConnectedError unless connected?
98
+
99
+ channel = @request_dispatcher.add_request(query)
100
+ begin
101
+ @transport.write(query)
102
+ channel.dequeue
103
+ rescue Async::Stop, Async::TimeoutError
104
+ close(check_requests: false)
105
+ raise
108
106
  end
107
+ end
109
108
 
110
- def inspect
111
- "<#{self.class} url=#{@url} connected=#{connected?}>"
112
- end
109
+ def inspect
110
+ "<#{self.class} url=#{@url} connected=#{connected?}>"
111
+ end
113
112
 
114
- def to_s
115
- inspect
116
- end
113
+ def to_s
114
+ inspect
115
+ end
117
116
 
118
- private
117
+ private
119
118
 
120
- # This might be overridden in successors
121
- def build_transport
122
- Transport.new(@url, parent: @parent, **@client_options)
123
- end
119
+ # This might be overridden in successors
120
+ def build_transport
121
+ Grumlin::Transport.new(@url, parent: @parent, **@client_options)
124
122
  end
125
123
  end
@@ -1,41 +1,41 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- module Grumlin
4
- class Config
5
- attr_accessor :url, :pool_size, :client_concurrency, :client_factory, :provider
6
-
7
- SUPPORTED_PROVIDERS = %i[neptune tinkergraph].freeze
8
-
9
- DEFAULT_MIDDLEWARES = Middleware::Builder.new do |b|
10
- b.use Middlewares::SerializeToSteps
11
- b.use Middlewares::ApplyShortcuts
12
- b.use Middlewares::SerializeToBytecode
13
- b.use Middlewares::BuildQuery
14
- b.use Middlewares::CastResults
15
- b.use Middlewares::RunQuery
16
- end.freeze
17
-
18
- class ConfigurationError < Grumlin::Error; end
19
-
20
- class UnknownProviderError < ConfigurationError; end
21
-
22
- def initialize
23
- @pool_size = 10
24
- @client_concurrency = 5
25
- @provider = :tinkergraph
26
- @client_factory = ->(url, parent) { Grumlin::Client.new(url, parent: parent) }
27
- end
3
+ class Grumlin::Config
4
+ attr_accessor :url, :pool_size, :client_concurrency, :client_factory, :provider
5
+
6
+ SUPPORTED_PROVIDERS = [:neptune, :tinkergraph].freeze
7
+
8
+ DEFAULT_MIDDLEWARES = Grumlin::Middlewares::Builder.new do |b|
9
+ b.use Grumlin::Middlewares::SerializeToSteps
10
+ b.use Grumlin::Middlewares::ApplyShortcuts
11
+ b.use Grumlin::Middlewares::SerializeToBytecode
12
+ b.use Grumlin::Middlewares::BuildQuery
13
+ b.use Grumlin::Middlewares::CastResults
14
+ b.use Grumlin::Middlewares::RunQuery
15
+ end
28
16
 
29
- def middlewares
30
- @middlewares ||= Middleware::Builder.new do |b|
31
- b.use DEFAULT_MIDDLEWARES
32
- end
33
- end
17
+ class ConfigurationError < Grumlin::Error; end
18
+
19
+ class UnknownProviderError < ConfigurationError; end
34
20
 
35
- def validate!
36
- return if SUPPORTED_PROVIDERS.include?(provider.to_sym)
21
+ def initialize
22
+ @pool_size = 10
23
+ @client_concurrency = 5
24
+ @provider = :tinkergraph
25
+ @client_factory = ->(url, parent) { Grumlin::Client.new(url, parent: parent) }
26
+ end
37
27
 
38
- raise UnknownProviderError, "provider '#{provider}' is unknown. Supported providers: #{SUPPORTED_PROVIDERS}"
28
+ def middlewares
29
+ @middlewares ||= Grumlin::Middlewares::Builder.new do |b|
30
+ b.use DEFAULT_MIDDLEWARES
39
31
  end
32
+ yield(@middlewares) if block_given?
33
+ @middlewares
34
+ end
35
+
36
+ def validate!
37
+ return if SUPPORTED_PROVIDERS.include?(provider.to_sym)
38
+
39
+ raise UnknownProviderError, "provider '#{provider}' is unknown. Supported providers: #{SUPPORTED_PROVIDERS}"
40
40
  end
41
41
  end
@@ -1,25 +1,23 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- module Grumlin
4
- class DummyTransaction < Transaction
5
- attr_reader :uuid
3
+ class Grumlin::DummyTransaction < Grumlin::Transaction
4
+ attr_reader :uuid
6
5
 
7
- include Console
6
+ include Console
8
7
 
9
- def initialize(traversal_start_class, middlewares:, pool: nil) # rubocop:disable Lint/MissingSuper, Lint/UnusedMethodArgument
10
- @traversal_start_class = traversal_start_class
8
+ def initialize(traversal_start_class, middlewares:, pool: nil) # rubocop:disable Lint/MissingSuper, Lint/UnusedMethodArgument
9
+ @traversal_start_class = traversal_start_class
11
10
 
12
- logger.info(self) do
13
- "#{Grumlin.config.provider} does not support transactions. commit and rollback are ignored, data will be saved"
14
- end
11
+ logger.info(self) do
12
+ "#{Grumlin.config.provider} does not support transactions. commit and rollback are ignored, data will be saved"
15
13
  end
14
+ end
16
15
 
17
- def commit
18
- nil
19
- end
16
+ def commit
17
+ nil
18
+ end
20
19
 
21
- def rollback
22
- nil
23
- end
20
+ def rollback
21
+ nil
24
22
  end
25
23
  end
data/lib/grumlin/edge.rb CHANGED
@@ -1,28 +1,26 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- module Grumlin
4
- class Edge
5
- attr_reader :label, :id, :inVLabel, :outVLabel, :inV, :outV
3
+ class Grumlin::Edge
4
+ attr_reader :label, :id, :inVLabel, :outVLabel, :inV, :outV
6
5
 
7
- def initialize(label:, id:, inVLabel:, outVLabel:, inV:, outV:)
8
- @label = label
9
- @id = Typing.cast(id)
10
- @inVLabel = inVLabel
11
- @outVLabel = outVLabel
12
- @inV = Typing.cast(inV)
13
- @outV = Typing.cast(outV)
14
- end
6
+ def initialize(label:, id:, inVLabel:, outVLabel:, inV:, outV:)
7
+ @label = label
8
+ @id = Grumlin::Typing.cast(id)
9
+ @inVLabel = inVLabel
10
+ @outVLabel = outVLabel
11
+ @inV = Grumlin::Typing.cast(inV)
12
+ @outV = Grumlin::Typing.cast(outV)
13
+ end
15
14
 
16
- def ==(other)
17
- self.class == other.class && @label == other.label && @id == other.id
18
- end
15
+ def ==(other)
16
+ self.class == other.class && @label == other.label && @id == other.id
17
+ end
19
18
 
20
- def inspect
21
- "e[#{@id}][#{@outV}-#{@label}->#{@inV}]"
22
- end
19
+ def inspect
20
+ "e[#{@id}][#{@outV}-#{@label}->#{@inV}]"
21
+ end
23
22
 
24
- def to_s
25
- inspect
26
- end
23
+ def to_s
24
+ inspect
27
25
  end
28
26
  end
@@ -1,15 +1,11 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- module Grumlin
4
- module Expressions
5
- module Cardinality
6
- SUPPORTED_STEPS = Grumlin.definitions.dig(:expressions, :cardinality).map(&:to_sym).freeze
3
+ module Grumlin::Expressions::Cardinality
4
+ SUPPORTED_STEPS = Grumlin.definitions.dig(:expressions, :cardinality).map(&:to_sym).freeze
7
5
 
8
- class << self
9
- extend Expression
6
+ class << self
7
+ extend Grumlin::Expressions::Expression
10
8
 
11
- define_steps(SUPPORTED_STEPS, "Cardinality")
12
- end
13
- end
9
+ define_steps(SUPPORTED_STEPS, "Cardinality")
14
10
  end
15
11
  end
@@ -1,15 +1,11 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- module Grumlin
4
- module Expressions
5
- module Column
6
- SUPPORTED_STEPS = Grumlin.definitions.dig(:expressions, :column).map(&:to_sym).freeze
3
+ module Grumlin::Expressions::Column
4
+ SUPPORTED_STEPS = Grumlin.definitions.dig(:expressions, :column).map(&:to_sym).freeze
7
5
 
8
- class << self
9
- extend Expression
6
+ class << self
7
+ extend Grumlin::Expressions::Expression
10
8
 
11
- define_steps(SUPPORTED_STEPS, "Column")
12
- end
13
- end
9
+ define_steps(SUPPORTED_STEPS, "Column")
14
10
  end
15
11
  end
@@ -1,17 +1,13 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- module Grumlin
4
- module Expressions
5
- module Expression
6
- def define_steps(steps, tool_name)
7
- steps.each do |step|
8
- define_method step do
9
- name = "@#{step}"
10
- return instance_variable_get(name) if instance_variable_defined?(name)
3
+ module Grumlin::Expressions::Expression
4
+ def define_steps(steps, tool_name)
5
+ steps.each do |step|
6
+ define_method step do
7
+ name = "@#{step}"
8
+ return instance_variable_get(name) if instance_variable_defined?(name)
11
9
 
12
- instance_variable_set(name, TypedValue.new(type: tool_name, value: step))
13
- end
14
- end
10
+ instance_variable_set(name, Grumlin::TypedValue.new(type: tool_name, value: step))
15
11
  end
16
12
  end
17
13
  end
@@ -1,15 +1,11 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- module Grumlin
4
- module Expressions
5
- module Operator
6
- SUPPORTED_STEPS = Grumlin.definitions.dig(:expressions, :operator).map(&:to_sym).freeze
3
+ module Grumlin::Expressions::Operator
4
+ SUPPORTED_STEPS = Grumlin.definitions.dig(:expressions, :operator).map(&:to_sym).freeze
7
5
 
8
- class << self
9
- extend Expression
6
+ class << self
7
+ extend Grumlin::Expressions::Expression
10
8
 
11
- define_steps(SUPPORTED_STEPS, "Operator")
12
- end
13
- end
9
+ define_steps(SUPPORTED_STEPS, "Operator")
14
10
  end
15
11
  end
@@ -1,15 +1,11 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- module Grumlin
4
- module Expressions
5
- module Order
6
- SUPPORTED_STEPS = Grumlin.definitions.dig(:expressions, :order).map(&:to_sym).freeze
3
+ module Grumlin::Expressions::Order
4
+ SUPPORTED_STEPS = Grumlin.definitions.dig(:expressions, :order).map(&:to_sym).freeze
7
5
 
8
- class << self
9
- extend Expression
6
+ class << self
7
+ extend Grumlin::Expressions::Expression
10
8
 
11
- define_steps(SUPPORTED_STEPS, "Order")
12
- end
13
- end
9
+ define_steps(SUPPORTED_STEPS, "Order")
14
10
  end
15
11
  end
@@ -1,39 +1,35 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- module Grumlin
4
- module Expressions
5
- class P
6
- class Predicate
7
- attr_reader :namespace, :name, :value, :type
3
+ class Grumlin::Expressions::P
4
+ class Predicate
5
+ attr_reader :namespace, :name, :value, :type
8
6
 
9
- def initialize(namespace, name, value:, type: nil)
10
- @namespace = namespace
11
- @name = name
12
- @value = value
13
- @type = type
14
- end
15
- end
7
+ def initialize(namespace, name, value:, type: nil)
8
+ @namespace = namespace
9
+ @name = name
10
+ @value = value
11
+ @type = type
12
+ end
13
+ end
16
14
 
17
- class << self
18
- # TODO: support more predicates
19
- %i[eq gt lt neq].each do |predicate|
20
- define_method predicate do |*args|
21
- Predicate.new("P", predicate, value: args[0])
22
- end
23
- end
15
+ class << self
16
+ # TODO: support more predicates
17
+ [:eq, :gt, :lt, :neq].each do |predicate|
18
+ define_method predicate do |*args|
19
+ Predicate.new("P", predicate, value: args[0])
20
+ end
21
+ end
24
22
 
25
- %i[within without].each do |predicate|
26
- define_method predicate do |*args|
27
- args = if args.count == 1 && args[0].is_a?(Array)
28
- args[0]
29
- elsif args.count == 1 && args[0].is_a?(Set)
30
- args[0].to_a
31
- else
32
- args.to_a
33
- end
34
- Predicate.new("P", predicate, value: args, type: "List")
35
- end
36
- end
23
+ [:within, :without].each do |predicate|
24
+ define_method predicate do |*args|
25
+ args = if args.count == 1 && args[0].is_a?(Array)
26
+ args[0]
27
+ elsif args.count == 1 && args[0].is_a?(Set)
28
+ args[0].to_a
29
+ else
30
+ args.to_a
31
+ end
32
+ Predicate.new("P", predicate, value: args, type: "List")
37
33
  end
38
34
  end
39
35
  end
@@ -1,15 +1,11 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- module Grumlin
4
- module Expressions
5
- module Pop
6
- SUPPORTED_STEPS = Grumlin.definitions.dig(:expressions, :pop).map(&:to_sym).freeze
3
+ module Grumlin::Expressions::Pop
4
+ SUPPORTED_STEPS = Grumlin.definitions.dig(:expressions, :pop).map(&:to_sym).freeze
7
5
 
8
- class << self
9
- extend Expression
6
+ class << self
7
+ extend Grumlin::Expressions::Expression
10
8
 
11
- define_steps(SUPPORTED_STEPS, "Pop")
12
- end
13
- end
9
+ define_steps(SUPPORTED_STEPS, "Pop")
14
10
  end
15
11
  end
@@ -1,15 +1,11 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- module Grumlin
4
- module Expressions
5
- module Scope
6
- SUPPORTED_STEPS = Grumlin.definitions.dig(:expressions, :scope).map(&:to_sym).freeze
3
+ module Grumlin::Expressions::Scope
4
+ SUPPORTED_STEPS = Grumlin.definitions.dig(:expressions, :scope).map(&:to_sym).freeze
7
5
 
8
- class << self
9
- extend Expression
6
+ class << self
7
+ extend Grumlin::Expressions::Expression
10
8
 
11
- define_steps(SUPPORTED_STEPS, "Scope")
12
- end
13
- end
9
+ define_steps(SUPPORTED_STEPS, "Scope")
14
10
  end
15
11
  end
@@ -1,15 +1,11 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- module Grumlin
4
- module Expressions
5
- module T
6
- SUPPORTED_STEPS = Grumlin.definitions.dig(:expressions, :t).map(&:to_sym).freeze
3
+ module Grumlin::Expressions::T
4
+ SUPPORTED_STEPS = Grumlin.definitions.dig(:expressions, :t).map(&:to_sym).freeze
7
5
 
8
- class << self
9
- extend Expression
6
+ class << self
7
+ extend Grumlin::Expressions::Expression
10
8
 
11
- define_steps(SUPPORTED_STEPS, "T")
12
- end
13
- end
9
+ define_steps(SUPPORTED_STEPS, "T")
14
10
  end
15
11
  end
@@ -1,14 +1,10 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- module Grumlin
4
- module Expressions
5
- class TextP < P
6
- class << self
7
- %i[containing endingWith notContaining notEndingWith notStartingWith startingWith].each do |predicate|
8
- define_method predicate do |*args|
9
- P::Predicate.new("TextP", predicate, value: args[0])
10
- end
11
- end
3
+ class Grumlin::Expressions::TextP < Grumlin::Expressions::P
4
+ class << self
5
+ [:containing, :endingWith, :notContaining, :notEndingWith, :notStartingWith, :startingWith].each do |predicate|
6
+ define_method predicate do |*args|
7
+ P::Predicate.new("TextP", predicate, value: args[0])
12
8
  end
13
9
  end
14
10
  end