neo4j-core 4.0.7 → 5.0.0.rc.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -36,54 +36,79 @@ module Neo4j
36
36
  "Enumerable query: '#{@query}'"
37
37
  end
38
38
 
39
- def each(&block)
39
+ def each
40
40
  @response.each_data_row do |row|
41
- yield(row.each_with_index.each_with_object(struct.new) do |(value, i), result|
42
- result[columns[i].to_sym] = value
43
- end)
41
+ yield struct_rows(row)
42
+ end
43
+ end
44
+
45
+ def struct_rows(row)
46
+ struct.new.tap do |result|
47
+ row.each_with_index { |value, i| result[columns[i]] = value }
44
48
  end
45
49
  end
46
50
  end
47
51
 
48
- def to_struct_enumeration(cypher = '')
52
+ EMPTY_STRING = ''
53
+ def to_struct_enumeration(cypher = EMPTY_STRING)
49
54
  HashEnumeration.new(self, cypher)
50
55
  end
51
56
 
52
- def to_node_enumeration(cypher = '', session = Neo4j::Session.current)
57
+ def to_node_enumeration(cypher = EMPTY_STRING, session = Neo4j::Session.current)
53
58
  Enumerator.new do |yielder|
54
59
  @result_index = 0
55
60
  to_struct_enumeration(cypher).each do |row|
56
61
  @row_index = 0
57
- yielder << row.each_pair.each_with_object(@struct.new) do |(column, value), result|
58
- result[column] = map_row_value(value, session)
59
- @row_index += 1
60
- end
62
+ yielder << row_pair_in_struct(row, session)
61
63
  @result_index += 1
62
64
  end
63
65
  end
64
66
  end
65
67
 
68
+ def row_pair_in_struct(row, session)
69
+ @struct.new.tap do |result|
70
+ row.each_pair do |column, value|
71
+ result[column] = map_row_value(value, session)
72
+ @row_index += 1
73
+ end
74
+ end
75
+ end
76
+
66
77
  def map_row_value(value, session)
67
78
  if value.is_a?(Hash)
68
79
  hash_value_as_object(value, session)
69
80
  elsif value.is_a?(Array)
70
- value.map { |v| map_row_value(v, session) }
81
+ value.map! { |v| map_row_value(v, session) }
71
82
  else
72
83
  value
73
84
  end
74
85
  end
75
86
 
76
87
  def hash_value_as_object(value, session)
77
- return value unless value['labels'] || value['type'] || transaction_response?
88
+ data = case
89
+ when transaction_response?
90
+ add_transaction_entity_id
91
+ mapped_rest_data
92
+ when value[:labels] || value[:type]
93
+ add_entity_id(value)
94
+ value
95
+ else
96
+ return value
97
+ end
98
+ basic_obj = (node?(value) ? CypherNode : CypherRelationship).new(session, data)
99
+ unwrapped? ? basic_obj : basic_obj.wrapper
100
+ end
101
+
102
+ def unwrapped!
103
+ @_unwrapped_obj = true
104
+ end
105
+
106
+ def unwrapped?
107
+ !!@_unwrapped_obj
108
+ end
78
109
 
79
- is_node, data = if transaction_response?
80
- add_transaction_entity_id
81
- [!mapped_rest_data['start'], mapped_rest_data]
82
- elsif value['labels'] || value['type']
83
- add_entity_id(value)
84
- [value['labels'], value]
85
- end
86
- (is_node ? CypherNode : CypherRelationship).new(session, data).wrapper
110
+ def node?(value)
111
+ transaction_response? ? !mapped_rest_data[:start] : value[:labels]
87
112
  end
88
113
 
89
114
  attr_reader :struct
@@ -95,17 +120,17 @@ module Neo4j
95
120
 
96
121
  def entity_data(id = nil)
97
122
  if @uncommited
98
- data = @data.first['row'].first
99
- data.is_a?(Hash) ? {'data' => data, 'id' => id} : data
123
+ data = @data.first[:row].first
124
+ data.is_a?(Hash) ? {data: data, id: id} : data
100
125
  else
101
126
  data = @data[0][0]
102
127
  data.is_a?(Hash) ? add_entity_id(data) : data
103
128
  end
104
129
  end
105
130
 
106
- def first_data(id = nil)
131
+ def first_data
107
132
  if @uncommited
108
- data = @data.first['row'].first
133
+ @data.first[:row].first
109
134
  # data.is_a?(Hash) ? {'data' => data, 'id' => id} : data
110
135
  else
111
136
  data = @data[0][0]
@@ -114,45 +139,57 @@ module Neo4j
114
139
  end
115
140
 
116
141
  def add_entity_id(data)
117
- data.merge!('id' => self.class.id_from_url(data['self']))
142
+ data[:id] = if data[:metadata] && data[:metadata][:id]
143
+ data[:metadata][:id]
144
+ else
145
+ self.class.id_from_url(data[:self])
146
+ end
147
+ data
118
148
  end
119
149
 
120
150
  def add_transaction_entity_id
121
- mapped_rest_data.merge!('id' => mapped_rest_data['self'].split('/').last.to_i)
151
+ mapped_rest_data[:id] = mapped_rest_data[:self].split('/').last.to_i
152
+ mapped_rest_data
122
153
  end
123
154
 
124
155
  def error?
125
156
  !!@error
126
157
  end
127
158
 
159
+ RETRYABLE_ERROR_STATUSES = %w(DeadlockDetectedException AcquireLockTimeoutException ExternalResourceFailureException UnknownFailureException)
160
+ def retryable_error?
161
+ return unless error?
162
+ RETRYABLE_ERROR_STATUSES.include?(@error_status)
163
+ end
164
+
128
165
  def data?
129
- !response.body['data'].nil?
166
+ !response.body[:data].nil?
130
167
  end
131
168
 
132
169
  def raise_unless_response_code(code)
133
- fail "Response code #{response.status}, expected #{code} for #{response.headers['location']}, #{response.body}" unless response.status == code
170
+ fail "Response code #{response.status}, expected #{code} for #{response.headers[:location]}, #{response.body}" unless response.status == code
134
171
  end
135
172
 
136
173
  def each_data_row
137
174
  if @uncommited
138
- data.each { |r| yield r['row'] }
175
+ data.each { |r| yield r[:row] }
139
176
  else
140
177
  data.each { |r| yield r }
141
178
  end
142
179
  end
143
180
 
144
- def set_data(data, columns)
145
- @data = data
146
- @columns = columns
147
- @struct = columns.empty? ? Object.new : Struct.new(*columns.map(&:to_sym))
181
+ def set_data(response)
182
+ @data = response[:data]
183
+ @columns = response[:columns]
184
+ @struct = @columns.empty? ? Object.new : Struct.new(*@columns.map(&:to_sym))
148
185
  self
149
186
  end
150
187
 
151
- def set_error(error_msg, error_status, error_core)
188
+ def set_error(error)
152
189
  @error = true
153
- @error_msg = error_msg
154
- @error_status = error_status
155
- @error_code = error_core
190
+ @error_msg = error[:message]
191
+ @error_status = error[:status] || error[:exception] || error[:code]
192
+ @error_code = error[:code] || error[:fullname]
156
193
  self
157
194
  end
158
195
 
@@ -170,9 +207,9 @@ module Neo4j
170
207
  def self.create_with_no_tx(response)
171
208
  case response.status
172
209
  when 200
173
- CypherResponse.new(response).set_data(response.body['data'], response.body['columns'])
210
+ new(response).set_data(response.body)
174
211
  when 400
175
- CypherResponse.new(response).set_error(response.body['message'], response.body['exception'], response.body['fullname'])
212
+ new(response).set_error(response.body)
176
213
  else
177
214
  fail "Unknown response code #{response.status} for #{response.env[:url]}"
178
215
  end
@@ -181,20 +218,18 @@ module Neo4j
181
218
  def self.create_with_tx(response)
182
219
  fail "Unknown response code #{response.status} for #{response.request_uri}" unless response.status == 200
183
220
 
184
- first_result = response.body['results'][0]
185
- cr = CypherResponse.new(response, true)
186
-
187
- if response.body['errors'].empty?
188
- cr.set_data(first_result['data'], first_result['columns'])
189
- else
190
- first_error = response.body['errors'].first
191
- cr.set_error(first_error['message'], first_error['status'], first_error['code'])
221
+ new(response, true).tap do |cr|
222
+ body = response.body
223
+ if body[:errors].empty?
224
+ cr.set_data(body[:results].first)
225
+ else
226
+ cr.set_error(body[:errors].first)
227
+ end
192
228
  end
193
- cr
194
229
  end
195
230
 
196
231
  def transaction_response?
197
- response.respond_to?('body') && !response.body['commit'].nil?
232
+ response.respond_to?(:body) && !response.body[:commit].nil?
198
233
  end
199
234
 
200
235
  def rest_data
@@ -203,7 +238,8 @@ module Neo4j
203
238
  end
204
239
 
205
240
  def rest_data_with_id
206
- rest_data.merge!('id' => mapped_rest_data['self'].split('/').last.to_i)
241
+ rest_data[:id] = mapped_rest_data[:self].split('/').last.to_i
242
+ rest_data
207
243
  end
208
244
 
209
245
  class << self
@@ -219,7 +255,7 @@ module Neo4j
219
255
  attr_reader :result_index
220
256
 
221
257
  def mapped_rest_data
222
- response.body['results'][0]['data'][result_index]['rest'][row_index]
258
+ response.body[:results][0][:data][result_index][:rest][row_index]
223
259
  end
224
260
  end
225
261
  end
@@ -1,8 +1,7 @@
1
1
  module Neo4j
2
2
  module Server
3
- # Plugin
4
- Neo4j::Session.register_db(:server_db) do |*url_opts|
5
- Neo4j::Server::CypherSession.open(*url_opts)
3
+ Neo4j::Session.register_db(:server_db) do |endpoint_url, url_opts|
4
+ Neo4j::Server::CypherSession.open(endpoint_url, url_opts)
6
5
  end
7
6
 
8
7
  class CypherSession < Neo4j::Session
@@ -26,9 +25,10 @@ module Neo4j
26
25
  init_params = params[:initialize] && params.delete(:initialize)
27
26
  conn = Faraday.new(url, init_params) do |b|
28
27
  b.request :basic_auth, params[:basic_auth][:username], params[:basic_auth][:password] if params[:basic_auth]
29
- b.request :json
28
+ b.request :multi_json
30
29
  # b.response :logger
31
- b.response :json, content_type: 'application/json'
30
+
31
+ b.response :multi_json, symbolize_keys: true, content_type: 'application/json'
32
32
  # b.use Faraday::Response::RaiseError
33
33
  b.use Faraday::Adapter::NetHttpPersistent
34
34
  # b.adapter Faraday.default_adapter
@@ -52,17 +52,14 @@ module Neo4j
52
52
  end
53
53
 
54
54
  def self.establish_session(root_data, connection)
55
- data_url = root_data['data']
55
+ data_url = root_data[:data]
56
56
  data_url << '/' unless data_url.nil? || data_url.end_with?('/')
57
57
  CypherSession.new(data_url, connection)
58
58
  end
59
59
 
60
60
  def self.extract_basic_auth(url, params)
61
61
  return unless url && URI(url).userinfo
62
- params[:basic_auth] = {
63
- username: URI(url).user,
64
- password: URI(url).password
65
- }
62
+ params[:basic_auth] = {username: URI(url).user, password: URI(url).password}
66
63
  end
67
64
 
68
65
  private_class_method :extract_basic_auth
@@ -80,12 +77,12 @@ module Neo4j
80
77
  end
81
78
 
82
79
  def version
83
- resource_data ? resource_data['neo4j_version'] : ''
80
+ resource_data ? resource_data[:neo4j_version] : ''
84
81
  end
85
82
 
86
83
  def initialize_resource(data_url)
87
84
  response = @connection.get(data_url)
88
- expect_response_code(response, 200)
85
+ expect_response_code!(response, 200)
89
86
  data_resource = response.body
90
87
  fail "No data_resource for #{response.body}" unless data_resource
91
88
  # store the resource data
@@ -98,43 +95,27 @@ module Neo4j
98
95
  end
99
96
 
100
97
  def begin_tx
101
- if Neo4j::Transaction.current
102
- # Handle nested transaction "placebo transaction"
103
- Neo4j::Transaction.current.push_nested!
104
- else
105
- wrap_resource(@connection)
106
- end
98
+ Neo4j::Transaction.current ? Neo4j::Transaction.current.push_nested! : wrap_resource(@connection)
107
99
  Neo4j::Transaction.current
108
100
  end
109
101
 
110
102
  def create_node(props = nil, labels = [])
111
- id = _query_or_fail(cypher_string(labels, props), true, cypher_prop_list(props))
112
- value = props.nil? ? id : {'id' => id, 'metadata' => {'labels' => labels}, 'data' => props}
103
+ id = _query_or_fail(cypher_string(labels, props), true, cypher_prop_list!(props))
104
+ value = props.nil? ? id : {id: id, metadata: {labels: labels}, data: props}
113
105
  CypherNode.new(self, value)
114
106
  end
115
107
 
116
108
  def load_node(neo_id)
117
- load_entity(CypherNode, _query("MATCH (n) WHERE ID(n) = #{neo_id} RETURN n"))
109
+ query.unwrapped.match(:n).where(n: {neo_id: neo_id}).pluck(:n).first
118
110
  end
119
111
 
120
112
  def load_relationship(neo_id)
121
- load_entity(CypherRelationship, _query("MATCH (n)-[r]-() WHERE ID(r) = #{neo_id} RETURN r"))
122
- end
123
-
124
- def load_entity(clazz, cypher_response)
125
- return nil if cypher_response.data.nil? || cypher_response.data[0].nil?
126
- data = if cypher_response.transaction_response?
127
- cypher_response.rest_data_with_id
128
- else
129
- cypher_response.first_data
130
- end
131
-
132
- if cypher_response.error?
133
- cypher_response.raise_error
134
- elsif cypher_response.error_msg =~ /not found/ # Ugly that the Neo4j API gives us this error message
135
- return nil
113
+ query.unwrapped.optional_match('(n)-[r]-()').where(r: {neo_id: neo_id}).pluck(:r).first
114
+ rescue Neo4j::Session::CypherError => cypher_error
115
+ if cypher_error.message.match(/not found$/)
116
+ nil
136
117
  else
137
- clazz.new(self, data)
118
+ raise cypher_error
138
119
  end
139
120
  end
140
121
 
@@ -143,17 +124,17 @@ module Neo4j
143
124
  end
144
125
 
145
126
  def uniqueness_constraints(label)
146
- schema_properties("#{@resource_url}schema/constraint/#{label}/uniqueness")
127
+ schema_properties("/db/data/schema/constraint/#{label}/uniqueness")
147
128
  end
148
129
 
149
130
  def indexes(label)
150
- schema_properties("#{@resource_url}schema/index/#{label}")
131
+ schema_properties("/db/data/schema/index/#{label}")
151
132
  end
152
133
 
153
134
  def schema_properties(query_string)
154
135
  response = @connection.get(query_string)
155
- expect_response_code(response, 200)
156
- {property_keys: response.body.map { |row| row['property_keys'].map(&:to_sym) }}
136
+ expect_response_code!(response, 200)
137
+ {property_keys: response.body.map! { |row| row[:property_keys].map(&:to_sym) }}
157
138
  end
158
139
 
159
140
  def find_all_nodes(label_name)
@@ -163,17 +144,15 @@ module Neo4j
163
144
  def find_nodes(label_name, key, value)
164
145
  value = "'#{value}'" if value.is_a? String
165
146
 
166
- response = _query_or_fail <<-CYPHER
167
- MATCH (n:`#{label_name}`)
168
- WHERE n.#{key} = #{value}
169
- RETURN ID(n)
170
- CYPHER
147
+ response = _query_or_fail("MATCH (n:`#{label_name}`) WHERE n.#{key} = #{value} RETURN ID(n)")
171
148
  search_result_to_enumerable_first_column(response)
172
149
  end
173
150
 
174
151
  def query(*args)
175
152
  if [[String], [String, Hash]].include?(args.map(&:class))
176
- query, params = args[0, 2]
153
+ query = args[0]
154
+ params = args[1]
155
+
177
156
  response = _query(query, params)
178
157
  response.raise_error if response.error?
179
158
  response.to_node_enumeration(query)
@@ -183,77 +162,85 @@ module Neo4j
183
162
  end
184
163
  end
185
164
 
186
- def _query_data(q)
187
- r = _query_or_fail(q, true)
188
- # the response is different if we have a transaction or not
189
- Neo4j::Transaction.current ? r : r['data']
165
+ def _query_data(query)
166
+ r = _query_or_fail(query, true)
167
+ Neo4j::Transaction.current ? r : r[:data]
190
168
  end
191
169
 
192
- def _query_or_fail(q, single_row = false, params = {})
193
- if q.is_a?(::Neo4j::Core::Query)
194
- cypher = q.to_cypher
195
- params = q.send(:merge_params).merge(params)
196
- q = cypher
170
+ DEFAULT_RETRY_COUNT = ENV['NEO4J_RETRY_COUNT'].nil? ? 10 : ENV['NEO4J_RETRY_COUNT'].to_i
171
+
172
+ def _query_or_fail(query, single_row = false, params = {}, retry_count = DEFAULT_RETRY_COUNT)
173
+ query, params = query_and_params(query, params)
174
+
175
+ response = _query(query, params)
176
+ if response.error?
177
+ _retry_or_raise(query, params, single_row, retry_count, response)
178
+ else
179
+ single_row ? response.first_data : response
197
180
  end
181
+ end
198
182
 
199
- response = _query(q, params)
200
- response.raise_error if response.error?
201
- single_row ? response.first_data : response
183
+ def query_and_params(query_or_query_string, params)
184
+ if query_or_query_string.is_a?(::Neo4j::Core::Query)
185
+ cypher = query_or_query_string.to_cypher
186
+ [cypher, query_or_query_string.send(:merge_params).merge(params)]
187
+ else
188
+ [query_or_query_string, params]
189
+ end
202
190
  end
203
191
 
204
- def _query_entity_data(q, id = nil, params = nil)
205
- response = _query(q, params)
206
- response.raise_error if response.error?
207
- response.entity_data(id)
192
+ def _retry_or_raise(query, params, single_row, retry_count, response)
193
+ response.raise_error unless response.retryable_error?
194
+ retry_count > 0 ? _query_or_fail(query, single_row, params, retry_count - 1) : response.raise_error
208
195
  end
209
196
 
210
- def _query(q, params = nil)
211
- # puts "q #{q}"
197
+ def _query_entity_data(query, id = nil, params = {})
198
+ _query_response(query, params).entity_data(id)
199
+ end
200
+
201
+ def _query_response(query, params = {})
202
+ _query(query, params).tap do |response|
203
+ response.raise_error if response.error?
204
+ end
205
+ end
206
+
207
+ def _query(query, params = {})
208
+ query, params = query_and_params(query, params)
209
+
212
210
  curr_tx = Neo4j::Transaction.current
213
211
  if curr_tx
214
- curr_tx._query(q, params)
212
+ curr_tx._query(query, params)
215
213
  else
216
- url = resource_url('cypher')
217
- q = params.nil? ? {'query' => q} : {'query' => q, 'params' => params}
218
- response = @connection.post(url, q)
214
+ url = resource_url(:cypher)
215
+ query = params.nil? ? {'query' => query} : {'query' => query, 'params' => params}
216
+ response = @connection.post(url, query)
219
217
  CypherResponse.create_with_no_tx(response)
220
218
  end
221
219
  end
222
220
 
223
221
  def search_result_to_enumerable_first_column(response)
224
222
  return [] unless response.data
225
- if Neo4j::Transaction.current
226
- search_result_to_enumerable_first_column_with_tx(response)
227
- else
228
- search_result_to_enumerable_first_column_without_tx(response)
229
- end
230
- end
231
223
 
232
- def search_result_to_enumerable_first_column_with_tx(response)
233
224
  Enumerator.new do |yielder|
234
225
  response.data.each do |data|
235
- data['row'].each do |id|
236
- yielder << CypherNode.new(self, id).wrapper
226
+ if Neo4j::Transaction.current
227
+ data[:row].each do |id|
228
+ yielder << CypherNode.new(self, id).wrapper
229
+ end
230
+ else
231
+ yielder << CypherNode.new(self, data[0]).wrapper
237
232
  end
238
233
  end
239
234
  end
240
235
  end
241
236
 
242
- def search_result_to_enumerable_first_column_without_tx(response)
243
- Enumerator.new do |yielder|
244
- response.data.each do |data|
245
- yielder << CypherNode.new(self, data[0]).wrapper
246
- end
247
- end
248
- end
249
-
250
- def map_column(key, map, data)
251
- if map[key] == :node
252
- CypherNode.new(self, data).wrapper
253
- elsif map[key] == :rel || map[:key] || :relationship
254
- CypherRelationship.new(self, data)
255
- else
256
- data
237
+ EMPTY = ''
238
+ def self.log_with
239
+ clear, yellow, cyan = %W(\e[0m \e[33m \e[36m)
240
+ ActiveSupport::Notifications.subscribe('neo4j.cypher_query') do |_, start, finish, _id, payload|
241
+ ms = (finish - start) * 1000
242
+ params_string = (payload[:params].size > 0 ? "| #{payload[:params].inspect}" : EMPTY)
243
+ yield(" #{cyan}#{payload[:context]}#{clear} #{yellow}#{ms.round}ms#{clear} #{payload[:cypher]} #{params_string}")
257
244
  end
258
245
  end
259
246
  end
@@ -2,9 +2,9 @@ module Neo4j
2
2
  module Server
3
3
  # The CypherTransaction object lifecycle is as follows:
4
4
  # * It is initialized with the transactional endpoint URL and the connection object to use for communication. It does not communicate with the server to create this.
5
- # * The first query within the transaction sets the commit and execution addresses, :commit_url and :exec_url.
5
+ # * The first query within the transaction sets the commit and execution addresses, :commit_url and :query_url.
6
6
  # * At any time, `failure` can be called to mark a transaction failed and trigger a rollback upon closure.
7
- # * `close` is called to end the transaction. It calls `_commit_tx` or `_delete_tx`.
7
+ # * `close` is called to end the transaction. It calls `commit` or `delete`.
8
8
  #
9
9
  # If a transaction is created and then closed without performing any queries, an OpenStruct is returned that behaves like a successfully closed query.
10
10
  class CypherTransaction
@@ -12,7 +12,7 @@ module Neo4j
12
12
  include Neo4j::Core::CypherTranslator
13
13
  include Resource
14
14
 
15
- attr_reader :commit_url, :exec_url, :base_url, :connection
15
+ attr_reader :commit_url, :query_url, :base_url, :connection
16
16
 
17
17
  def initialize(url, session_connection)
18
18
  @base_url = url
@@ -26,49 +26,58 @@ module Neo4j
26
26
  statement = {statement: cypher_query, parameters: params, resultDataContents: ROW_REST}
27
27
  body = {statements: [statement]}
28
28
 
29
- response = exec_url && commit_url ? connection.post(exec_url, body) : register_urls(body)
30
- _create_cypher_response(response)
29
+ response = @query_url ? query(body) : start(body)
30
+
31
+ create_cypher_response(response)
31
32
  end
32
33
 
33
- def _delete_tx
34
- _tx_query(:delete, exec_url, headers: resource_headers)
34
+ def start(body)
35
+ request(:post, @base_url, 201, body).tap do |response|
36
+ @commit_url = response.body[:commit]
37
+ @query_url = response.headers[:Location]
38
+
39
+ fail "NO ENDPOINT URL #{connection} : HEAD: #{response.headers.inspect}" if !@query_url || @query_url.empty?
40
+
41
+ init_resource_data(response.body, @base_url)
42
+ end
35
43
  end
36
44
 
37
- def _commit_tx
38
- _tx_query(:post, commit_url, nil)
45
+ def query(body)
46
+ request(:post, @query_url, 200, body)
39
47
  end
40
48
 
41
- private
49
+ def delete
50
+ return empty_response if !@commit_url || expired?
42
51
 
43
- def _tx_query(action, endpoint, headers = {})
44
- return empty_response if !commit_url || expired?
45
- response = connection.send(action, endpoint, headers)
46
- expect_response_code(response, 200)
47
- response
52
+ request(:delete, @query_url, 200, nil, resource_headers)
48
53
  end
49
54
 
50
- def register_urls(body)
51
- response = connection.post(base_url, body)
52
- @commit_url = response.body['commit']
53
- @exec_url = response.headers['Location']
54
- fail "NO ENDPOINT URL #{connection} : HEAD: #{response.headers.inspect}" if !exec_url || exec_url.empty?
55
- init_resource_data(response.body, base_url)
56
- expect_response_code(response, 201)
57
- response
55
+ def commit
56
+ return empty_response if !@commit_url || expired?
57
+
58
+ request(:post, @commit_url, 200, nil, resource_headers)
59
+ end
60
+
61
+ private
62
+
63
+ def request(action, endpoint_url, expected_code = 200, body = nil, headers = {})
64
+ connection.send(action, endpoint_url, body, headers).tap do |response|
65
+ expect_response_code!(response, expected_code)
66
+ end
58
67
  end
59
68
 
60
- def _create_cypher_response(response)
61
- first_result = response.body['results'][0]
69
+ def create_cypher_response(response)
70
+ first_result = response.body[:results][0]
62
71
 
63
- cr = CypherResponse.new(response, true)
64
- if response.body['errors'].empty?
65
- cr.set_data(first_result['data'], first_result['columns'])
66
- else
67
- first_error = response.body['errors'].first
68
- expired if first_error['message'].match(/Unrecognized transaction id/)
69
- cr.set_error(first_error['message'], first_error['code'], first_error['code'])
72
+ CypherResponse.new(response, true).tap do |cypher_response|
73
+ if response.body[:errors].empty?
74
+ cypher_response.set_data(first_result)
75
+ else
76
+ first_error = response.body[:errors].first
77
+ mark_expired if first_error[:message].match(/Unrecognized transaction id/)
78
+ cypher_response.set_error(first_error)
79
+ end
70
80
  end
71
- cr
72
81
  end
73
82
 
74
83
  def empty_response