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 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