grumlin 0.16.1 → 0.17.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: ce713ebd08c676dfe38124e0286963ea18ee8d5d51f678096fd5f2ae8c28c51c
4
- data.tar.gz: 6cd25c9ac701a2276fdb470b55b4ebaf123323521c6cd8d4d87365b68d604426
3
+ metadata.gz: 2d63d3923f895d20e89fd1647495d99bb3a97888689c8f25c34973355d7c80e1
4
+ data.tar.gz: 878546a65736522f3c1f00f42741b6b207e992a1983321205d05406e0a74ed6b
5
5
  SHA512:
6
- metadata.gz: 81b5b522b5d183240d27cb36285f448e4918386cd267ea84fcffb2cc763d156d272844a4ffab2e00999d5c5be129930d905220506e07702ff150c49ac7388d1b
7
- data.tar.gz: f4d56b0a66d91f8f454964a8d42de46fa0b6b85595c48e67e09875e01bfdb96eb131e0c6cb5ec395ebeb7dda59c45ff67c445f88e75a12a03436689d9ba14279
6
+ metadata.gz: 60bf726b74019b36bb0437c78b97ea1ba78703058ba2a619805e0081d49158f30bb67cc7918b959cf0375c37a5600632a1df805563edccb0266b71c9ab70f1de
7
+ data.tar.gz: cc7dc9ecfd45c67b28301593d3ba60e471e7a9993460ce39dcb912bbed5fb0aa01ed25bcf52f49634f704d6732ba563d849fb8d492276f19fe83e5e8531a8181
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- grumlin (0.16.1)
4
+ grumlin (0.17.0)
5
5
  async-pool (~> 0.3)
6
6
  async-websocket (~> 0.19)
7
7
  oj (~> 3.12)
@@ -44,7 +44,7 @@ GEM
44
44
  benchmark (0.1.1)
45
45
  childprocess (4.0.0)
46
46
  concurrent-ruby (1.1.8)
47
- console (1.14.0)
47
+ console (1.15.0)
48
48
  fiber-local
49
49
  diff-lcs (1.4.4)
50
50
  docile (1.4.0)
data/README.md CHANGED
@@ -150,7 +150,7 @@ shortcuts to make gremlin code more rubyish. Can be used as a drop in replacemen
150
150
  or `Grumlin::Shortcuts` can be inherited**, successors don't need to extend them again and have access to shortcuts
151
151
  defined in the ancestor.
152
152
 
153
- **Using**:
153
+ **Definition**
154
154
 
155
155
  ```ruby
156
156
  class MyRepository
@@ -167,15 +167,45 @@ class MyRepository
167
167
  hasAll(T.label => :triangle, color: color)
168
168
  end
169
169
 
170
- # g and __ are already aware of shortcuts
171
- def red_triangles
170
+ # g and __ are already aware of shortcuts
171
+ query(:triangles_with_color, return_mode: :list) do |color| # :list is the default return mode, also possible: :none, :single, :traversal
172
172
  g.V.hasLabel(:triangle)
173
- .hasColor("red")
174
- .toList
173
+ .hasColor(color)
175
174
  end
175
+ # Note that when using the `query` one does not need to call a termination step like `next` or `toList`,
176
+ # repository does it automatically in according to the `return_mode` parameter.
176
177
  end
177
178
  ```
178
179
 
180
+ Each `return_mode` is mapped to a particular termination step:
181
+ - `:list` - `toList`
182
+ - `:single` - `next`
183
+ - `:none` - `iterate`
184
+ - `:traversal` - do not execute the query and return the traversal as is
185
+
186
+ **Usage**
187
+
188
+ To execute the query defined in a query block one simply needs to call a method with the same name:
189
+
190
+ `MyRepository.new.triangles_with_color(:red)`
191
+
192
+ One can also override the `return_mode`:
193
+
194
+ `MyRepository.new.triangles_with_color(:red, query_params: { return_mode: :single })`
195
+
196
+ or even pass a block to the method and a raw traversal will be yielded:
197
+ ```ruby
198
+ MyRepository.new.triangles_with_color(:red) do |t|
199
+ t.has(:other_property, :some_value).toList
200
+ end
201
+ ```
202
+ it may be useful for debugging. Note that one needs to call a termination step manually in this case.
203
+
204
+ `query` also provides a helper for profiling requests:
205
+ `MyRepository.new.triangles_with_color(:red, query_params: { profile: true })`
206
+
207
+ method will return profiling data of the results.
208
+
179
209
  #### IRB
180
210
 
181
211
  An example of how to start an IRB session with support for executing gremlin queries:
@@ -2,6 +2,13 @@
2
2
 
3
3
  module Grumlin
4
4
  module Repository
5
+ RETURN_MODES = {
6
+ list: :toList,
7
+ none: :iterate,
8
+ single: :next,
9
+ traversal: :nil
10
+ }.freeze
11
+
5
12
  module InstanceMethods
6
13
  def __
7
14
  TraversalStart.new(self.class.shortcuts)
@@ -19,5 +26,53 @@ module Grumlin
19
26
 
20
27
  base.shortcuts_from(Grumlin::Shortcuts::Properties)
21
28
  end
29
+
30
+ def query(name, return_mode: :list, postprocess_with: nil, &query_block) # rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
31
+ return_mode = validate_return_mode!(return_mode)
32
+ postprocess_with = validate_postprocess_with!(postprocess_with)
33
+
34
+ define_method name do |*args, query_params: {}, **params, &block|
35
+ t = instance_exec(*args, **params, &query_block)
36
+ return t if self.class.empty_result?(t)
37
+
38
+ unless t.is_a?(Grumlin::Action)
39
+ raise WrongQueryResult,
40
+ "queries must return #{Grumlin::Action}, nil or an empty collection. Given: #{t.class}"
41
+ end
42
+
43
+ return block.call(t) unless block.nil?
44
+
45
+ return t.profile.next if query_params[:profile] == true
46
+
47
+ return_mode = self.class.validate_return_mode!(query_params[:return_mode] || return_mode)
48
+
49
+ return t if return_mode == :traversal
50
+
51
+ t.public_send(RETURN_MODES[return_mode]).tap do |result|
52
+ return postprocess_with.call(result) if postprocess_with.respond_to?(:call)
53
+ return send(postprocess_with, result) unless postprocess_with.nil?
54
+ end
55
+ end
56
+ end
57
+
58
+ def validate_return_mode!(return_mode)
59
+ return return_mode if RETURN_MODES.key?(return_mode)
60
+
61
+ raise ArgumentError, "unsupported return mode #{return_mode}. Supported modes: #{RETURN_MODES.keys}"
62
+ end
63
+
64
+ def validate_postprocess_with!(postprocess_with)
65
+ if postprocess_with.nil? || postprocess_with.is_a?(Symbol) ||
66
+ postprocess_with.is_a?(String) || postprocess_with.respond_to?(:call)
67
+ return postprocess_with
68
+ end
69
+
70
+ raise ArgumentError,
71
+ "postprocess_with must be a String, Symbol or a callable object, given: #{postprocess_with.class}"
72
+ end
73
+
74
+ def empty_result?(result)
75
+ result.nil? || (result.respond_to?(:empty?) && result.empty?)
76
+ end
22
77
  end
23
78
  end
@@ -69,7 +69,7 @@ module Grumlin
69
69
  def cast_map(value)
70
70
  Hash[*value].transform_keys do |key|
71
71
  next key.to_sym if key.respond_to?(:to_sym)
72
- next cast(key) if key[:@type]
72
+ next cast(key) if key[:@type] # TODO: g.V.group.by(:none_existing_property).next
73
73
 
74
74
  raise UnknownMapKey, key, value
75
75
  end.transform_values { |v| cast(v) }
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Grumlin
4
- VERSION = "0.16.1"
4
+ VERSION = "0.17.0"
5
5
  end
data/lib/grumlin.rb CHANGED
@@ -100,6 +100,10 @@ module Grumlin
100
100
  end
101
101
  end
102
102
 
103
+ class RepositoryError < Error; end
104
+
105
+ class WrongQueryResult < RepositoryError; end
106
+
103
107
  class Config
104
108
  attr_accessor :url, :pool_size, :client_concurrency, :client_factory
105
109
 
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.16.1
4
+ version: 0.17.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-03-15 00:00:00.000000000 Z
11
+ date: 2022-03-30 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: async-pool