neoon 0.0.4 → 0.0.5

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: b1ff7ac30436f19194698ede55cfe68529918122
4
- data.tar.gz: 3b62de2caf2e48745e2f67d9705490b5cfe43e48
3
+ metadata.gz: 28243d5e5b0830a48aa0df05d3b94dfc9b7bf3b7
4
+ data.tar.gz: 5d7b6ea2499ed9302ae792a566410a33a60047fe
5
5
  SHA512:
6
- metadata.gz: a5baa0e81c289446fee6744879834a45a878b976d265c10c871b0b666bdcc9c69f581108a665c1959533e0f73ae9241a2247da2d822043ac5ff8d084e708b0ed
7
- data.tar.gz: dcb1ea83f6b94370962a93f9a829833f2a1e1f6f882e1ea4458b530f56f8776b078644433bce4090b99b56b683743fae9e444ad645db6234a0be490497ee1026
6
+ metadata.gz: f5be28a492cfdfbfc9356c9e7eb69b5511df51d5cb90353b857dfc195a46a489d8e9f0e9d719d0e34a056d11ee77a13bd64e0394575c485ea29bb9f91711b6f7
7
+ data.tar.gz: 603ac48d81ef63a99a6004d64356a5cadfe9345a83e79568ffa262c3f4a20380990cbe64717a7ad8be80c24d753f5d8f7bde1223b3f4d61700cd0f4525e1bc54
data/README.md CHANGED
@@ -83,12 +83,12 @@ end
83
83
  This will be used internally to auto index models nodes.
84
84
 
85
85
  ```ruby
86
- Topic.neo_index_list #=> [:name, :slug]
86
+ Topic.neo_index_list #=> { :name => true, :slug => "UNIQUENESS" }
87
87
 
88
88
  #
89
89
  # Sync the indexed nodes as described in each model config. It returns the indexed fields.
90
90
  # Remember, this will be called on each model on the boot if preload_models set to true.
91
- Topic.neo_schema_update #=> [:name, :slug]
91
+ Topic.neo_schema_update #=> { :name => true, :slug => "UNIQUENESS" }
92
92
  ```
93
93
 
94
94
  ---
@@ -98,13 +98,13 @@ Topic.neo_schema_update #=> [:name, :slug]
98
98
  `Neoon::Cypher::InstanceQuery` should be initialized with an Class name or `label`. You can use `Neoon::Cypher::Query` to manually create indexes, constraints, etc.
99
99
 
100
100
  ```ruby
101
- l = Neoon::Cypher::Query.new('Person') #=> #<Neoon::Cypher::Query:0x007fe8926d2068 @label="Person">
101
+ l = Neoon::Cypher::Query.new('Person')
102
102
 
103
- l.create_index(:name).run
104
- # l.drop_index(:name).run
103
+ l.create_index(:name)
104
+ # l.drop_index(:name)
105
105
 
106
- l.create_constraint(:username).run
107
- # l.drop_constraint(:username).run
106
+ l.create_constraint(:username)
107
+ # l.drop_constraint(:username)
108
108
 
109
109
  l.list_indexes #=> { :name => true, :username => "UNIQUENESS" }
110
110
  ```
@@ -121,25 +121,25 @@ Use it with Struct:
121
121
 
122
122
  ```ruby
123
123
  Customer = Struct.new(:id, :neo_node_properties)
124
- cus = Customer.new(50, {:name => 'Julie', :address => 'PS'}) #=> #<Neoon::Cypher::InstanceQuery:0x007feb35953d00 @id=50, @label="Customer", @args={:name=>"Julie", :address=>"PS"}>
124
+ cus = Customer.new(50, {:name => 'Julie', :address => 'PS'})
125
125
 
126
126
  c = Neoon::Cypher::InstanceQuery.new(cus)
127
127
 
128
- c.find_node.run #=> Return node in Neo4j if already saved
129
- c.create_node.run #=> Create object node / or update it
130
- c.delete_node.run #=> Remove object node
128
+ c.find_node #=> Return node in Neo4j if already saved
129
+ c.create_node #=> Create object node / or update it
130
+ c.delete_node #=> Remove object node
131
131
  ```
132
132
 
133
- Note that the key of finding nodes in Neo4j is `id` as saved in Neo4j with key `db_id`.
133
+ Note that the key of finding nodes in Neo4j is `id` as saved in Neo4j with key `_id`.
134
134
 
135
135
  Another example on the model we defined above:
136
136
 
137
137
  ```ruby
138
- t = Neoon::Cypher::InstanceQuery.new(Topic.first) #=> #<Neoon::Cypher::InstanceQuery:0x007fe894410b98 @id=1, @label="Topic", @args={...}>
138
+ t = Neoon::Cypher::InstanceQuery.new(Topic.first)
139
139
 
140
- t.find_node.run #=> Returns node in Neo4j if already saved
141
- t.create_node.run #=> Create object node / or update it
142
- t.delete_node.run #=> Remove object node
140
+ t.find_node #=> Returns node in Neo4j if already saved
141
+ t.create_node #=> Create object node / or update it
142
+ t.delete_node #=> Remove object node
143
143
  ```
144
144
 
145
145
  ---
@@ -6,15 +6,7 @@ module Faraday
6
6
  @app.call(env).on_complete do |env|
7
7
  case env[:status]
8
8
  when (400..499)
9
- body = JSON.parse(env[:body])
10
- raise "Neoon::Error::#{body["cause"]["exception"]}".constantize, "#{{
11
- :message => body["message"],
12
- :exception => body["exception"],
13
- :cause => {
14
- :message => body["cause"]["message"],
15
- :exception => body["cause"]["exception"]
16
- }
17
- } if env[:body]}"
9
+ raise "Neoon::Error::#{JSON.parse(env[:body])["cause"]["exception"]}".constantize.new(env[:response], env[:response].body)
18
10
  when (500..599)
19
11
  raise 'Something went error with Neo4j server.'
20
12
  end
@@ -5,10 +5,10 @@ module Neoon
5
5
  attr_reader :connection
6
6
 
7
7
  def initialize(url)
8
- @uri = URI.parse(url)
9
- end_point = "#{@uri.scheme}://#{@uri.host}:#{@uri.port}#{@uri.path}"
8
+ uri = URI.parse(url)
9
+ end_point = "#{uri.scheme}://#{uri.host}:#{uri.port}#{uri.path}"
10
10
  @connection ||= Faraday.new(end_point, connection_options.merge(:builder => middleware))
11
- @connection.basic_auth(@uri.user, @uri.password) if @uri.user && @uri.password
11
+ @connection.basic_auth(uri.user, uri.password) if uri.user && uri.password
12
12
  end
13
13
 
14
14
  include Request
@@ -26,7 +26,7 @@ module Neoon
26
26
  :request => {
27
27
  :open_timeout => 5,
28
28
  :timeout => 10,
29
- },
29
+ }
30
30
  }
31
31
  end
32
32
 
@@ -2,27 +2,21 @@ module Neoon
2
2
  module Cypher
3
3
  class Handler
4
4
 
5
- attr_reader :query, :args
5
+ attr_reader :query, :args, :result
6
6
 
7
7
  def initialize(hash)
8
- @query = hash[:query]
9
- @args = hash[:args]
10
- end
8
+ @query = hash[:query]
9
+ @args = hash[:args]
11
10
 
12
- def to_cypher
13
- if query.is_a?(Array)
14
- query.map { |q| q.gsub(/\s+/, ' ').strip }
15
- else
16
- query.gsub(/\s+/, ' ').strip
11
+ @result = begin
12
+ make_cypher_request(query, args)
13
+ rescue Exception => e
14
+ { :error => e }
17
15
  end
18
16
  end
19
17
 
20
- def run
21
- if query.is_a?(Array)
22
- query.each { |q| make_cypher_request(q, args) }
23
- else
24
- make_cypher_request(query, args)
25
- end
18
+ def to_cypher
19
+ [query.gsub(/\s+/, ' ').strip, args]
26
20
  end
27
21
 
28
22
  protected
@@ -7,37 +7,10 @@ module Neoon
7
7
  def initialize(object)
8
8
  @id = object.id
9
9
  @label = object.class.name
10
- @args = object.neo_node_properties
10
+ @args = object.neo_node_properties.merge(:_id => id)
11
11
  end
12
12
 
13
- def find_node
14
- cypher_query = <<-CYPHER
15
- MATCH node:#{label} WHERE node._id = #{id}
16
- RETURN node
17
- CYPHER
18
- cypherable(:query => cypher_query)
19
- end
20
-
21
- def create_node
22
- cypher_query = <<-CYPHER
23
- MERGE (node:#{label} { _id: #{id} })
24
- ON CREATE node SET node = {props}
25
- ON MATCH node SET node = {props}
26
- RETURN node
27
- CYPHER
28
- cypherable(:query => cypher_query, :args => {:props => args})
29
- end
30
- alias_method :update_node, :create_node
31
- alias_method :save_node, :create_node
32
-
33
- def delete_node
34
- cypher_query = <<-CYPHER
35
- MATCH node:#{label}
36
- WHERE node._id = #{id}
37
- DELETE node
38
- CYPHER
39
- cypherable(:query => cypher_query)
40
- end
13
+ include Neoon::Cypher::Node::Operations
41
14
 
42
15
  protected
43
16
 
@@ -0,0 +1,43 @@
1
+ module Neoon
2
+ module Cypher
3
+ module Node
4
+ module Operations
5
+
6
+ def find_node
7
+ cypher_query = <<-CYPHER
8
+ MATCH node:#{label} WHERE node._id = #{id}
9
+ RETURN node
10
+ CYPHER
11
+ cypherable(:query => cypher_query)
12
+ end
13
+
14
+ def save_node
15
+ # since you can't update a constrain with same value
16
+ # we have to remove the node and re-create it
17
+ # other way ???
18
+ delete_node unless (label.constantize.respond_to?(:neo_schema_index_keys) ? label.constantize.neo_schema_index_keys : Neoon::Cypher::Query.new(label).list_indexes).select{|k,v| v=='UNIQUENESS'}.empty?
19
+
20
+ cypher_query = <<-CYPHER
21
+ MERGE (node:#{label} { _id: #{id} })
22
+ ON CREATE node SET node = {props}
23
+ ON MATCH node SET node = {props}
24
+ RETURN node
25
+ CYPHER
26
+ cypherable(:query => cypher_query, :args => {:props => args})
27
+ end
28
+ alias_method :update_node, :save_node
29
+ alias_method :create_node, :save_node
30
+
31
+ def delete_node
32
+ cypher_query = <<-CYPHER
33
+ MATCH node:#{label}
34
+ WHERE node._id = #{id}
35
+ DELETE node
36
+ CYPHER
37
+ cypherable(:query => cypher_query)
38
+ end
39
+
40
+ end
41
+ end
42
+ end
43
+ end
data/lib/neoon/error.rb CHANGED
@@ -1,11 +1,27 @@
1
1
  module Neoon
2
2
  module Error
3
3
 
4
- class Exception < StandardError; end
4
+ class Exception < StandardError
5
+ attr_reader :response
6
+
7
+ def initialize(response, message)
8
+ @response = response
9
+ super(message)
10
+ end
11
+ end
12
+
5
13
  class IndexException < Exception; end
6
14
  class SchemaException < Exception; end
7
15
  class CypherException < Exception; end
8
16
 
17
+ # custom
18
+ class NodeNotFoundException < Exception; end
19
+
20
+ # org.neo4j.kernel.impl.api.constraints
21
+ class ConstraintValidationKernelException < Exception; end
22
+ class UnableToValidateConstraintKernelException < Exception; end
23
+ class UniqueConstraintViolationKernelException < Exception; end
24
+
9
25
  # org.neo4j.kernel.api.exceptions
10
26
  class BeginTransactionFailureException < Exception; end
11
27
  class ConstraintCreationException < Exception; end
@@ -3,21 +3,26 @@ module Neoon
3
3
  module Node
4
4
 
5
5
  def neo_node
6
- _cypher_query.find_node.run.data.first.first.data
6
+ _node = _cypher_query.find_node.result.data
7
+ if _node.empty?
8
+ excep = { :message => "Cannot find node with id [#{_cypher_query.id}] in database.", :exception => "NodeNotFoundException" }
9
+ raise Neoon::Error::NodeNotFoundException.new excep, excep
10
+ end
11
+ _node.first.first.data
7
12
  end
8
13
 
9
14
  def neo_create
10
- _cypher_query.create_node.run.data
15
+ _cypher_query.create_node.result.data
11
16
  end
12
17
  alias_method :neo_save, :neo_create
13
18
  alias_method :neo_update, :neo_create
14
19
 
15
20
  def neo_destroy
16
- _cypher_query.delete_node.run.data
21
+ _cypher_query.delete_node.result.data
17
22
  end
18
23
 
19
24
  def neo_node_properties
20
- _neo_node.merge({ :_id => self.id })
25
+ _neo_node.merge(:_id => self.id)
21
26
  end
22
27
 
23
28
  protected
@@ -8,20 +8,18 @@ module Neoon
8
8
 
9
9
  def neo_index_create key
10
10
  if neo_schema_index_keys.select { |k,v| v == 'UNIQUENESS' }.include? key
11
- _cypher_query.create_constraint(key).run
11
+ _cypher_query.create_constraint(key)
12
12
  else
13
- _cypher_query.create_index(key).run
13
+ _cypher_query.create_index(key)
14
14
  end
15
- true
16
15
  end
17
16
 
18
17
  def neo_index_drop key
19
18
  if neo_index_list[key] == 'UNIQUENESS'
20
- _cypher_query.drop_constraint(key).run
19
+ _cypher_query.drop_constraint(key)
21
20
  else
22
- _cypher_query.drop_index(key).run
21
+ _cypher_query.drop_index(key)
23
22
  end
24
- true
25
23
  end
26
24
 
27
25
  def neo_index_drop_all
data/lib/neoon/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Neoon
2
- VERSION = '0.0.4'
2
+ VERSION = '0.0.5'
3
3
  end
data/lib/neoon.rb CHANGED
@@ -14,6 +14,7 @@ require 'neoon/cypher/handler'
14
14
  require 'neoon/cypher/schema/indexes'
15
15
  require 'neoon/cypher/schema/constraints'
16
16
  require 'neoon/cypher/query'
17
+ require 'neoon/cypher/node/operations'
17
18
  require 'neoon/cypher/instance_query'
18
19
 
19
20
  require 'neoon/model/config'
@@ -6,6 +6,14 @@ describe Neoon::Model::Config do
6
6
  require 'app/models/topic'
7
7
  end
8
8
 
9
+ it 'responds to .neoon' do
10
+ expect(Topic).to respond_to(:neoon)
11
+ end
12
+
13
+ it 'responds to .neo_model_config' do
14
+ expect(Topic).to respond_to(:neo_model_config)
15
+ end
16
+
9
17
  it 'returns the model config singleton' do
10
18
  expect(Topic.neo_model_config.class).to eq Neoon::Model::Config
11
19
  end
@@ -2,80 +2,54 @@ require 'spec_helper'
2
2
 
3
3
  describe Neoon::Model::Node do
4
4
 
5
- before :each do
5
+ before :all do
6
6
  require 'app/models/topic'
7
+ Topic.neo_schema_update
7
8
  Topic.destroy_all
8
9
  end
9
10
 
10
- context '' do
11
- it 'responds to neoon' do
12
- expect(Topic).to respond_to(:neoon)
13
- end
14
-
15
- it 'responds to neo_model_config' do
16
- expect(Topic).to respond_to(:neo_model_config)
17
- end
11
+ after :all do
12
+ Topic.destroy_all
18
13
  end
19
14
 
20
- context 'save' do
21
- before do
22
- @t = Topic.where(:name => 'Apple').first_or_create
23
- end
24
-
25
- after :all do
26
- Topic.destroy_all
27
- end
15
+ let(:topic) { Topic.where(:name => 'Apple').first_or_create }
28
16
 
29
- it 'responds to neo_save' do
30
- @t.respond_to?(:neo_save).should be_true
17
+ context 'save' do
18
+ it 'responds to .neo_save' do
19
+ expect(topic).to respond_to(:neo_save)
31
20
  end
32
21
 
33
22
  it 'sets neo_node_properties' do
34
- @t.neo_node_properties[:_id].should == @t.id
35
- @t.neo_node_properties[:name].should == @t.name
36
- @t.neo_node_properties[:slug].should == "#{@t.id}-#{@t.name.underscore}"
37
- end
38
-
39
- it 'saves to neo' do
40
- @t.neo_node._id.should == @t.id
23
+ expect(topic.neo_node_properties[:_id]).to eql topic.id
24
+ expect(topic.neo_node_properties[:name]).to eql topic.name
25
+ expect(topic.neo_node_properties[:slug]).to eql "#{topic.id}-#{topic.name.underscore}"
41
26
  end
42
27
 
43
- it 'updates to neo after assigning attr and save OR update_attribute()' do
44
- @t.name = 'MacBook'
45
- @t.save
46
- @t.neo_node.name.should == 'MacBook'
47
- @t.neo_node._id.should == @t.id
48
-
49
- @t.update_attribute(:name, 'Technology')
50
- @t.neo_node.name.should == 'Technology'
51
- @t.neo_node._id.should == @t.id
28
+ it 'has same values' do
29
+ expect(topic.neo_node._id).to eql topic.id
30
+ expect(topic.neo_node.name).to eql topic.name
31
+ expect(topic.neo_node.slug).to eql "#{topic.id}-#{topic.name.underscore}"
52
32
  end
53
33
 
54
34
  it 'has 1 record' do
55
- Topic.count.should == Neoon.db.q('MATCH n:Topic return n').data.count
56
- Topic.count.should == 1
35
+ expect(Topic.count).to eql Neoon.db.q('MATCH n:Topic return n').data.count
36
+ expect(Topic.count).to eql 1
57
37
  end
58
38
  end
59
39
 
60
40
  context 'destroy' do
61
- before do
62
- @t1 = Topic.where(:name => 'Amr').first_or_create
41
+ it 'responds to .neo_destroy' do
42
+ expect(topic).to respond_to(:neo_destroy)
63
43
  end
64
44
 
65
- after :all do
66
- Topic.destroy_all
45
+ it 'doesn\'t exist in neo4j' do
46
+ topic.destroy
47
+ expect { topic.neo_node }.to raise_error Neoon::Error::NodeNotFoundException
67
48
  end
68
49
 
69
- it 'responds to neo_destroy' do
70
- @t1.respond_to?(:neo_destroy).should be_true
71
- end
72
-
73
- it 'has 2 records' do
74
- topic = Topic.new name: 'Jo'
75
- topic.save
76
-
77
- Topic.count.should == Neoon.db.q('MATCH n:Topic return n').data.count
78
- Topic.count.should == 2
50
+ it 'has 0 record' do
51
+ expect(Topic.count).to eql Neoon.db.q('MATCH n:Topic return n').data.count
52
+ expect(Topic.count).to eql 0
79
53
  end
80
54
  end
81
55
 
@@ -9,7 +9,7 @@ describe Neoon::Model::Schema do
9
9
 
10
10
  context 'list index' do
11
11
  context 'from model config' do
12
- it 'responds to neo_schema_index_keys' do
12
+ it 'responds to .neo_schema_index_keys' do
13
13
  expect(Topic).to respond_to(:neo_schema_index_keys)
14
14
  end
15
15
  it 'returns all indexed properties' do
@@ -52,7 +52,7 @@ describe Neoon::Model::Schema do
52
52
  end
53
53
 
54
54
  context 'create index' do
55
- it 'responds to neo_index_create' do
55
+ it 'responds to .neo_index_create' do
56
56
  expect(Topic).to respond_to(:neo_index_create)
57
57
  end
58
58
 
@@ -63,8 +63,8 @@ describe Neoon::Model::Schema do
63
63
  expect(Topic.neo_index_create(:slug)).to be_true
64
64
  expect(Topic.neo_index_list.keys).to eql [:name, :slug]
65
65
 
66
- expect { Topic.neo_index_create(:name) }.to raise_error Neoon::Error::AlreadyIndexedException
67
- expect { Topic.neo_index_create(:slug) }.to raise_error Neoon::Error::AlreadyConstrainedException
66
+ expect(Topic.neo_index_create(:name).result[:error].class).to eq Neoon::Error::AlreadyIndexedException
67
+ expect(Topic.neo_index_create(:slug).result[:error].class).to eq Neoon::Error::AlreadyConstrainedException
68
68
  end
69
69
 
70
70
  end
@@ -75,7 +75,7 @@ describe Neoon::Model::Schema do
75
75
  Topic.neo_index_create(:slug)
76
76
  end
77
77
 
78
- it 'responds to neo_index_drop' do
78
+ it 'responds to .neo_index_drop' do
79
79
  expect(Topic).to respond_to(:neo_index_drop)
80
80
  end
81
81
 
@@ -86,8 +86,8 @@ describe Neoon::Model::Schema do
86
86
  expect(Topic.neo_index_drop(:slug)).to be_true
87
87
  expect(Topic.neo_index_list.keys).to eql []
88
88
 
89
- expect { Topic.neo_index_drop(:name) }.to raise_error Neoon::Error::DropIndexFailureException
90
- expect { Topic.neo_index_drop(:slug) }.to raise_error Neoon::Error::DropIndexFailureException
89
+ expect(Topic.neo_index_drop(:name).result[:error].class).to eq Neoon::Error::DropIndexFailureException
90
+ expect(Topic.neo_index_drop(:slug).result[:error].class).to eq Neoon::Error::DropIndexFailureException
91
91
  end
92
92
  end
93
93
 
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: neoon
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.4
4
+ version: 0.0.5
5
5
  platform: ruby
6
6
  authors:
7
7
  - Amr Tamimi
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2013-09-28 00:00:00.000000000 Z
11
+ date: 2013-10-16 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: faraday
@@ -157,6 +157,7 @@ files:
157
157
  - lib/neoon/config.rb
158
158
  - lib/neoon/cypher/handler.rb
159
159
  - lib/neoon/cypher/instance_query.rb
160
+ - lib/neoon/cypher/node/operations.rb
160
161
  - lib/neoon/cypher/query.rb
161
162
  - lib/neoon/cypher/schema/constraints.rb
162
163
  - lib/neoon/cypher/schema/indexes.rb