cypher_builder 0.0.3 → 0.0.4

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
  SHA1:
3
- metadata.gz: a296dcf5a03aae2c6ad43c178ed2150808b7cf56
4
- data.tar.gz: 586c6549b516bb866d454a3f1bdb26a9b9069bdd
3
+ metadata.gz: 875bb9cde808a0014d2d16a22bbba9f9fa050f32
4
+ data.tar.gz: a8dc8091e8b7862273da2c20d81b9c1a956c5e0d
5
5
  SHA512:
6
- metadata.gz: bbc86c29b2ee15020301b4317a95bdd74889624a272e8917a3b4732f87a8ed060ed65aa987700aa408d3c19053b4f65d6b3fb2e4f560e1e2401105ecd5c9db82
7
- data.tar.gz: c7b25acf4446a29861dadc71905c3af1458d05583c453be7f64481196ca4615b9a62dca49a9374a14208fa8d8045c6da17b03cce683bc1a7ed05f0ed6773dc5a
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
+ [![Gem Version](https://badge.fury.io/rb/cypher_builder.svg)](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.
@@ -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'
@@ -11,7 +11,7 @@ module CypherBuilder
11
11
  @an_alias = an_alias
12
12
  end
13
13
 
14
- def as_cypher(payload:, context: )
14
+ def as_cypher(payload:, context:)
15
15
  sprintf('%s AS %s', resolve(@field, payload: payload, context: context.add(self)), @an_alias)
16
16
  end
17
17
  end
File without changes
File without changes
@@ -3,6 +3,8 @@ module CypherBuilder::Resolver
3
3
  values.map do |v|
4
4
  if v.respond_to?(:as_cypher)
5
5
  v
6
+ elsif Symbol === v
7
+ AsIs.new(v)
6
8
  else
7
9
  Literal.new(v)
8
10
  end
File without changes
@@ -0,0 +1,16 @@
1
+ module CypherBuilder
2
+ def Limit(*args)
3
+ Limit.new(*args)
4
+ end
5
+
6
+ class Limit
7
+ include Resolver
8
+ def initialize(value)
9
+ @value = value
10
+ end
11
+
12
+ def as_cypher(_)
13
+ sprintf('LIMIT %d', @value.to_i)
14
+ end
15
+ end
16
+ end
@@ -11,7 +11,7 @@ module CypherBuilder
11
11
  end
12
12
 
13
13
  def as_cypher(payload:, context: )
14
- resolve(@parts, format: 'MATCH (%s)', separator: ', ', payload: payload, context: context.add(self))
14
+ resolve(@parts, format: 'MATCH %s', separator: ', ', payload: payload, context: context.add(self))
15
15
  end
16
16
  end
17
17
  end
@@ -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
- ::Field.new(@prefix, name)
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
@@ -1,3 +1,3 @@
1
1
  module CypherBuilder
2
- VERSION = '0.0.3'
2
+ VERSION = '0.0.4'
3
3
  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
- cypher_class = Cypher(Match(c),
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.3
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-21 00:00:00.000000000 Z
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/payload.rb
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