cypher_builder 0.0.3 → 0.0.4
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 +4 -4
- data/Guardfile +1 -1
- data/README.md +2 -0
- data/lib/cypher_builder.rb +11 -5
- data/lib/cypher_builder/alias.rb +1 -1
- data/lib/cypher_builder/{context.rb → infra/context.rb} +0 -0
- data/lib/cypher_builder/{payload.rb → infra/payload.rb} +0 -0
- data/lib/cypher_builder/{resolver.rb → infra/resolver.rb} +2 -0
- data/lib/cypher_builder/{runner.rb → infra/runner.rb} +0 -0
- data/lib/cypher_builder/limit.rb +16 -0
- data/lib/cypher_builder/match.rb +1 -1
- data/lib/cypher_builder/node.rb +2 -2
- data/lib/cypher_builder/order_by.rb +32 -0
- data/lib/cypher_builder/rel.rb +37 -0
- data/lib/cypher_builder/version.rb +1 -1
- data/spec/cypher_builder/cypher_spec.rb +16 -3
- data/spec/cypher_builder/node_spec.rb +3 -3
- data/spec/cypher_builder/order_by_spec.rb +24 -0
- data/spec/cypher_builder/rel_spec.rb +37 -0
- metadata +13 -6
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 875bb9cde808a0014d2d16a22bbba9f9fa050f32
|
4
|
+
data.tar.gz: a8dc8091e8b7862273da2c20d81b9c1a956c5e0d
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 1f67659909ed0a09587c0779e491980e4cd7745f9a83e6a14065c6b0f45cee962106b32863267b219ccd8450bdadfd849a41191854f3a674115823bd0207d6f8
|
7
|
+
data.tar.gz: 270f94f3052508ff0ac7ad7d74a63fb68a2b335eb4eb860fb033eea4eb0dfb6e1d330274e849624fb36a3c2a0dfed5a83e643ef6b745a599f81f492a550350e9
|
data/Guardfile
CHANGED
@@ -32,7 +32,7 @@ clearing :on
|
|
32
32
|
# * zeus: 'zeus rspec' (requires the server to be started separately)
|
33
33
|
# * 'just' rspec: 'rspec'
|
34
34
|
|
35
|
-
guard :rspec, cmd: 'bundle exec rspec' do
|
35
|
+
guard :rspec, cmd: 'bundle exec rspec', all_on_start: true, keep: true, all_after_pass: true, run_all: { cmd: 'bundle exec rspec -f progress' } do
|
36
36
|
require 'guard/rspec/dsl'
|
37
37
|
dsl = Guard::RSpec::Dsl.new(self)
|
38
38
|
|
data/README.md
CHANGED
@@ -1,5 +1,7 @@
|
|
1
1
|
# CypherBuilder
|
2
2
|
|
3
|
+
[](http://badge.fury.io/rb/cypher_builder)
|
4
|
+
|
3
5
|
Build Cypher query classes (Neo4j).
|
4
6
|
|
5
7
|
It creates Command classes that executes Cypher queries using Neography. The goal is make class creation easier.
|
data/lib/cypher_builder.rb
CHANGED
@@ -11,16 +11,20 @@ if defined?(::Neography)
|
|
11
11
|
CypherBuilder::Adapter::DEFAULT = CypherBuilder::Adapter::Neography.new
|
12
12
|
end
|
13
13
|
|
14
|
-
require 'cypher_builder/payload'
|
15
|
-
require 'cypher_builder/context'
|
16
|
-
require 'cypher_builder/resolver'
|
17
|
-
require 'cypher_builder/runner'
|
18
|
-
require 'cypher_builder/cypher'
|
14
|
+
require 'cypher_builder/infra/payload'
|
15
|
+
require 'cypher_builder/infra/context'
|
16
|
+
require 'cypher_builder/infra/resolver'
|
17
|
+
require 'cypher_builder/infra/runner'
|
19
18
|
|
19
|
+
# Not in Cypher
|
20
|
+
require 'cypher_builder/cypher'
|
20
21
|
require 'cypher_builder/as_is'
|
21
22
|
require 'cypher_builder/opt'
|
23
|
+
|
24
|
+
# Cypher
|
22
25
|
require 'cypher_builder/field'
|
23
26
|
require 'cypher_builder/node'
|
27
|
+
require 'cypher_builder/rel'
|
24
28
|
require 'cypher_builder/param'
|
25
29
|
require 'cypher_builder/literal'
|
26
30
|
require 'cypher_builder/match'
|
@@ -30,3 +34,5 @@ require 'cypher_builder/eql'
|
|
30
34
|
require 'cypher_builder/like'
|
31
35
|
require 'cypher_builder/return'
|
32
36
|
require 'cypher_builder/alias'
|
37
|
+
require 'cypher_builder/order_by'
|
38
|
+
require 'cypher_builder/limit'
|
data/lib/cypher_builder/alias.rb
CHANGED
File without changes
|
File without changes
|
File without changes
|
data/lib/cypher_builder/match.rb
CHANGED
@@ -11,7 +11,7 @@ module CypherBuilder
|
|
11
11
|
end
|
12
12
|
|
13
13
|
def as_cypher(payload:, context: )
|
14
|
-
resolve(@parts, format: 'MATCH
|
14
|
+
resolve(@parts, format: 'MATCH %s', separator: ', ', payload: payload, context: context.add(self))
|
15
15
|
end
|
16
16
|
end
|
17
17
|
end
|
data/lib/cypher_builder/node.rb
CHANGED
@@ -9,7 +9,7 @@ module CypherBuilder
|
|
9
9
|
end
|
10
10
|
|
11
11
|
def as_cypher(_ = nil)
|
12
|
-
[@prefix, *@labels].compact.join(':')
|
12
|
+
::Kernel.sprintf('(%s)', [@prefix, *@labels].compact.join(':'))
|
13
13
|
end
|
14
14
|
|
15
15
|
def respond_to_missing?(name, include_private = false)
|
@@ -17,7 +17,7 @@ module CypherBuilder
|
|
17
17
|
end
|
18
18
|
|
19
19
|
def method_missing(name, *_)
|
20
|
-
|
20
|
+
Field.new(@prefix, name)
|
21
21
|
end
|
22
22
|
end
|
23
23
|
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
module CypherBuilder
|
2
|
+
class MicroResolver < Struct.new(:payload, :context)
|
3
|
+
include Resolver
|
4
|
+
def execute(value)
|
5
|
+
resolve(value, payload: payload, context: context)
|
6
|
+
end
|
7
|
+
end
|
8
|
+
|
9
|
+
def OrderBy(first, *rest)
|
10
|
+
OrderBy.new(first, *rest)
|
11
|
+
end
|
12
|
+
|
13
|
+
class OrderBy
|
14
|
+
include Resolver
|
15
|
+
def initialize(first, *rest)
|
16
|
+
@parts = wrap(*([first] + rest))
|
17
|
+
end
|
18
|
+
|
19
|
+
def as_cypher(payload:, context:)
|
20
|
+
rsv = MicroResolver.new(payload, context.add(self))
|
21
|
+
|
22
|
+
ps = @parts.reduce([]) do |r, v|
|
23
|
+
if r.last && AsIs === v
|
24
|
+
r[0..-2] + [[r.last, rsv.execute(v)].join(' ')]
|
25
|
+
else
|
26
|
+
r + [rsv.execute(v)]
|
27
|
+
end
|
28
|
+
end
|
29
|
+
sprintf('ORDER BY %s', ps.join(', '))
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
module CypherBuilder
|
2
|
+
def Rel(prefix, labels: [])
|
3
|
+
Rel.new(prefix, labels: labels)
|
4
|
+
end
|
5
|
+
|
6
|
+
class Rel < BasicObject
|
7
|
+
def initialize(prefix, labels: [], from: nil, to: nil)
|
8
|
+
@prefix, @labels = prefix, ::Kernel.Array(labels)
|
9
|
+
@from, @to = from, to
|
10
|
+
end
|
11
|
+
|
12
|
+
def as_cypher(payload:, context:)
|
13
|
+
::Kernel.sprintf('%s-[%s]->%s',
|
14
|
+
(@from ? @from.as_cypher(payload: payload, context: context.add(self)) : '()'),
|
15
|
+
[@prefix, *@labels].compact.join(':'),
|
16
|
+
(@to ? @to.as_cypher(payload: payload, context: context.add(self)) : '()'))
|
17
|
+
end
|
18
|
+
|
19
|
+
def from(node = nil)
|
20
|
+
return Field.new(@prefix, 'from') if node == nil
|
21
|
+
Rel.new(@prefix, labels: @labels, from: node, to: @to)
|
22
|
+
end
|
23
|
+
|
24
|
+
def to(node = nil)
|
25
|
+
return Field.new(@prefix, 'to') if node == nil
|
26
|
+
Rel.new(@prefix, labels: @labels, from: @from, to: node)
|
27
|
+
end
|
28
|
+
|
29
|
+
def respond_to_missing?(name, include_private = false)
|
30
|
+
true
|
31
|
+
end
|
32
|
+
|
33
|
+
def method_missing(name, *_)
|
34
|
+
Field.new(@prefix, name)
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
@@ -24,14 +24,27 @@ describe Cypher do
|
|
24
24
|
cypher_class.new(adapter).execute
|
25
25
|
expect(adapter).to have_received(:execute).with('MATCH (c) RETURN c.name AS name', {})
|
26
26
|
end
|
27
|
+
it 'executes a query with relationships' do
|
28
|
+
c = Node('c')
|
29
|
+
n = Node('n')
|
30
|
+
r = Rel('r', labels: 'TEST')
|
31
|
+
cypher_class = Cypher(Match(r.from(c).to(n)),
|
32
|
+
Return(c.name))
|
33
|
+
cypher_class.new(adapter).execute
|
34
|
+
expect(adapter).to have_received(:execute).with('MATCH (c)-[r:TEST]->(n) RETURN c.name AS name', {})
|
35
|
+
end
|
27
36
|
it 'executes the most complex query possible (exercises everything currently implemented)' do
|
28
37
|
c = Node('c', labels: 'what')
|
29
|
-
|
38
|
+
n = Node('n')
|
39
|
+
r = Rel('r')
|
40
|
+
cypher_class = Cypher(Match(r.from(c).to(n)),
|
30
41
|
Where(And(Eql(c.stuff, Param('thing')),
|
31
42
|
Like(c.staff, 'test%'))),
|
32
|
-
Return(c.name, Alias(c.stuff, 'something'))
|
43
|
+
Return(c.name, Alias(c.stuff, 'something')),
|
44
|
+
OrderBy(c.name, :desc, c.stuff),
|
45
|
+
Limit(10))
|
33
46
|
cypher_class.new(adapter).execute(thing: 'of course')
|
34
|
-
expect(adapter).to have_received(:execute).with('MATCH (c:what) WHERE c.stuff = {thing} AND c.staff LIKE "test%" RETURN c.name AS name, c.stuff AS something', {thing: 'of course'})
|
47
|
+
expect(adapter).to have_received(:execute).with('MATCH (c:what)-[r]->(n) WHERE c.stuff = {thing} AND c.staff LIKE "test%" RETURN c.name AS name, c.stuff AS something ORDER BY c.name desc, c.stuff LIMIT 10', {thing: 'of course'})
|
35
48
|
end
|
36
49
|
context 'with Opt' do
|
37
50
|
before do
|
@@ -8,9 +8,9 @@ describe Node do
|
|
8
8
|
let(:node_multiple_labels) { Node('x', labels: ['uga', 'buga']) }
|
9
9
|
|
10
10
|
it 'converts to be used in "match"' do
|
11
|
-
expect(node.as_cypher).to eq 'x:uga'
|
12
|
-
expect(node_prefix_only.as_cypher).to eq 'x'
|
13
|
-
expect(node_multiple_labels.as_cypher).to eq 'x:uga:buga'
|
11
|
+
expect(node.as_cypher).to eq '(x:uga)'
|
12
|
+
expect(node_prefix_only.as_cypher).to eq '(x)'
|
13
|
+
expect(node_multiple_labels.as_cypher).to eq '(x:uga:buga)'
|
14
14
|
end
|
15
15
|
end
|
16
16
|
|
@@ -0,0 +1,24 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe OrderBy do
|
4
|
+
describe '#as_cypher' do
|
5
|
+
let(:payload) { instance_spy(Payload) }
|
6
|
+
let(:context) { instance_spy(Context) }
|
7
|
+
let(:c) { Node('c') }
|
8
|
+
|
9
|
+
it 'formats simple case' do
|
10
|
+
ob = OrderBy(c.something)
|
11
|
+
expect(ob.as_cypher(payload: payload, context: context)).to eq 'ORDER BY c.something'
|
12
|
+
end
|
13
|
+
|
14
|
+
it 'formats multiple elements' do
|
15
|
+
ob = OrderBy(c.something, c.other)
|
16
|
+
expect(ob.as_cypher(payload: payload, context: context)).to eq 'ORDER BY c.something, c.other'
|
17
|
+
end
|
18
|
+
|
19
|
+
it 'formats using :asc/:desc' do
|
20
|
+
ob = OrderBy(c.something, :desc, c.other)
|
21
|
+
expect(ob.as_cypher(payload: payload, context: context)).to eq 'ORDER BY c.something desc, c.other'
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Rel do
|
4
|
+
let(:rel) { Rel('x', labels: 'uga') }
|
5
|
+
|
6
|
+
describe '#as_cypher' do
|
7
|
+
let(:payload) { spy(Payload) }
|
8
|
+
let(:context) { spy(Context) }
|
9
|
+
|
10
|
+
it 'converts to be used in "match"' do
|
11
|
+
expect(rel.as_cypher(payload: payload, context: context)).to eq '()-[x:uga]->()'
|
12
|
+
|
13
|
+
c = Node('c')
|
14
|
+
nr = rel.from(c)
|
15
|
+
expect(nr.as_cypher(payload: payload, context: context)).to eq '(c)-[x:uga]->()'
|
16
|
+
|
17
|
+
x = Node('x', labels: 'test')
|
18
|
+
nr = rel.from(c).to(x)
|
19
|
+
expect(nr.as_cypher(payload: payload, context: context)).to eq '(c)-[x:uga]->(x:test)'
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
describe '#respond_to?' do
|
24
|
+
it 'is true for #as_cypher' do
|
25
|
+
expect(rel.respond_to?(:as_cypher)).to be_truthy
|
26
|
+
end
|
27
|
+
it 'is true for any method' do
|
28
|
+
expect(rel.respond_to?(:anything)).to be_truthy
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
describe 'any method' do
|
33
|
+
it 'responds with a Field' do
|
34
|
+
expect(rel.some_field).to be_instance_of Field
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: cypher_builder
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.4
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Ronie Uliana
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2015-01-
|
11
|
+
date: 2015-01-22 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -87,25 +87,30 @@ files:
|
|
87
87
|
- lib/cypher_builder/alias.rb
|
88
88
|
- lib/cypher_builder/and.rb
|
89
89
|
- lib/cypher_builder/as_is.rb
|
90
|
-
- lib/cypher_builder/context.rb
|
91
90
|
- lib/cypher_builder/cypher.rb
|
92
91
|
- lib/cypher_builder/eql.rb
|
93
92
|
- lib/cypher_builder/field.rb
|
93
|
+
- lib/cypher_builder/infra/context.rb
|
94
|
+
- lib/cypher_builder/infra/payload.rb
|
95
|
+
- lib/cypher_builder/infra/resolver.rb
|
96
|
+
- lib/cypher_builder/infra/runner.rb
|
94
97
|
- lib/cypher_builder/like.rb
|
98
|
+
- lib/cypher_builder/limit.rb
|
95
99
|
- lib/cypher_builder/literal.rb
|
96
100
|
- lib/cypher_builder/match.rb
|
97
101
|
- lib/cypher_builder/node.rb
|
98
102
|
- lib/cypher_builder/opt.rb
|
103
|
+
- lib/cypher_builder/order_by.rb
|
99
104
|
- lib/cypher_builder/param.rb
|
100
|
-
- lib/cypher_builder/
|
101
|
-
- lib/cypher_builder/resolver.rb
|
105
|
+
- lib/cypher_builder/rel.rb
|
102
106
|
- lib/cypher_builder/return.rb
|
103
|
-
- lib/cypher_builder/runner.rb
|
104
107
|
- lib/cypher_builder/version.rb
|
105
108
|
- lib/cypher_builder/where.rb
|
106
109
|
- spec/cypher_builder/adapter/neography_spec.rb
|
107
110
|
- spec/cypher_builder/cypher_spec.rb
|
108
111
|
- spec/cypher_builder/node_spec.rb
|
112
|
+
- spec/cypher_builder/order_by_spec.rb
|
113
|
+
- spec/cypher_builder/rel_spec.rb
|
109
114
|
- spec/spec_helper.rb
|
110
115
|
homepage: https://github.com/ruliana/cypher_builder
|
111
116
|
licenses:
|
@@ -135,4 +140,6 @@ test_files:
|
|
135
140
|
- spec/cypher_builder/adapter/neography_spec.rb
|
136
141
|
- spec/cypher_builder/cypher_spec.rb
|
137
142
|
- spec/cypher_builder/node_spec.rb
|
143
|
+
- spec/cypher_builder/order_by_spec.rb
|
144
|
+
- spec/cypher_builder/rel_spec.rb
|
138
145
|
- spec/spec_helper.rb
|