extendi-cassandra_object 1.0.5 → 1.0.6

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: 7f33ea4a5998a0a9037609d93c924510d3274631
4
- data.tar.gz: 34a9ee8f8b1069418b21752e1435f6ed16d461c1
3
+ metadata.gz: efe17be3c5e2444bff2078ff198a4103e590a436
4
+ data.tar.gz: 5bfd5a2ec7ab2393478ca07102627d62707422b2
5
5
  SHA512:
6
- metadata.gz: 8a4a65a5eadb7f814e16f7c35a84cac6359526e2e1fdce9114a787af32dd96d9340905ffe3240b1241c6c706f9accbc5a95036928d2d2851cd8e5839d3127dd4
7
- data.tar.gz: 668273dbc3a7113e62b874866aa3a27d72b90f8fb6003dd062c873a3ccea5cc7b477faebc2e1831f53043bdfe224ae3b5d5b751697ee191f849f5c4f3521972e
6
+ metadata.gz: 19d0cd635b148b38e5c9a85faab5595d65b45c94ec32387e3f7b2188e6e3cc3b5924e8bc63ad3d957ad25ab1ac5ca57cfe1d7fd02bed8429070e9c24cfa48cd0
7
+ data.tar.gz: 3b63a775a8af44163f983b5d933407aa977c5e33ea92f165723909fe806c07499600fca99eee34a98c8e4e175c5d88c40a686c400f2c5a1cb8a24fd3becfb0a3
@@ -2,7 +2,7 @@
2
2
 
3
3
  Gem::Specification.new do |s|
4
4
  s.name = 'extendi-cassandra_object'
5
- s.version = '1.0.5'
5
+ s.version = '1.0.6'
6
6
  s.description = 'Cassandra ActiveModel'
7
7
  s.summary = 'Cassandra ActiveModel'
8
8
  s.authors = ['Duccio Giovannelli', 'gotime']
@@ -30,14 +30,14 @@ module CassandraObject
30
30
  str << "ALLOW FILTERING" if @scope.klass.allow_filtering
31
31
  return [] << str.delete_if(&:blank?) * ' '
32
32
  end
33
- @scope.id_values.map { |id|
33
+ @scope.id_values.map do |id|
34
34
  str = [
35
35
  "SELECT #{select_string} FROM #{@scope.klass.column_family}",
36
36
  where_string_async(id)
37
37
  ]
38
38
  str << "ALLOW FILTERING" if @scope.klass.allow_filtering
39
39
  str.delete_if(&:blank?) * ' '
40
- }
40
+ end
41
41
  end
42
42
 
43
43
  def where_string_async(id)
@@ -110,17 +110,17 @@ module CassandraObject
110
110
  def execute(statement, arguments = [])
111
111
  ActiveSupport::Notifications.instrument('cql.cassandra_object', cql: statement) do
112
112
  type_hints = []
113
- arguments.map { |a| type_hints << CassandraObject::Types::TypeHelper.guess_type(a) } if !arguments.nil?
113
+ arguments.each { |a| type_hints << CassandraObject::Types::TypeHelper.guess_type(a) } unless arguments.nil?
114
114
  connection.execute statement, arguments: arguments, type_hints: type_hints, consistency: consistency, page_size: config[:page_size]
115
115
  end
116
116
  end
117
117
 
118
118
  def execute_async(queries, arguments = [])
119
- futures = queries.map { |q|
119
+ futures = queries.map do |q|
120
120
  ActiveSupport::Notifications.instrument('cql.cassandra_object', cql: q) do
121
121
  connection.execute_async q, arguments: arguments, consistency: consistency, page_size: config[:page_size]
122
122
  end
123
- }
123
+ end
124
124
  futures.map do |future|
125
125
  rows = future.get
126
126
  rows
@@ -169,7 +169,7 @@ module CassandraObject
169
169
 
170
170
  def delete(table, key, ids)
171
171
  ids = [ids] if !ids.is_a?(Array)
172
- statement = "DELETE FROM #{table} WHERE #{key} IN (#{ids.map { |id| "'#{id}'" }.join(',')})"
172
+ statement = "DELETE FROM #{table} WHERE #{key} IN (#{ids.map{|id| "'#{id}'"}.join(',')})"
173
173
  execute(statement, nil)
174
174
  end
175
175
 
@@ -30,17 +30,17 @@ module CassandraObject
30
30
  "SELECT #{select_string} FROM #{@scope.klass.column_family}",
31
31
  where_string_async(nil)
32
32
  ]
33
- str << "ALLOW FILTERING" if @scope.klass.allow_filtering
33
+ str << 'ALLOW FILTERING' if @scope.klass.allow_filtering
34
34
  return [] << str.delete_if(&:blank?) * ' '
35
35
  end
36
- @scope.id_values.map { |id|
36
+ @scope.id_values.map do |id|
37
37
  str = [
38
38
  "SELECT #{select_string} FROM #{@scope.klass.column_family}",
39
39
  where_string_async(id)
40
40
  ]
41
- str << "ALLOW FILTERING" if @scope.klass.allow_filtering
41
+ str << 'ALLOW FILTERING' if @scope.klass.allow_filtering
42
42
  str.delete_if(&:blank?) * ' '
43
- }
43
+ end
44
44
  end
45
45
 
46
46
  def where_string_async(id)
@@ -142,9 +142,9 @@ module CassandraObject
142
142
  query << " LIMIT #{scope.limit_value}" if scope.limit_value == 1
143
143
  ids = []
144
144
  new_next_cursor = nil
145
- execute_async([query], nil, per_page, next_cursor).map do |item|
146
- item.rows.map { |x| ids << x[primary_key_column] }
147
- new_next_cursor = item.paging_state if !item.last_page?
145
+ execute_async([query], nil, per_page, next_cursor).each do |item|
146
+ item.rows.each { |x| ids << x[primary_key_column] }
147
+ new_next_cursor = item.paging_state unless item.last_page?
148
148
  end
149
149
  return {ids: ids, new_next_cursor: new_next_cursor}
150
150
  end
@@ -154,19 +154,35 @@ module CassandraObject
154
154
  queries.compact! if queries.present?
155
155
  raise CassandraObject::RecordNotFound if !queries.present?
156
156
 
157
- arguments = scope.select_values.select { |sv| sv != :column1 }.map(&:to_s)
158
- arguments += scope.where_values.select.each_with_index { |_, i| i.odd? }.reject { |c| c.empty? }.map(&:to_s)
157
+ arguments = scope.select_values.select{ |sv| sv != :column1 }.map(&:to_s)
158
+ arguments += scope.where_values.select.each_with_index{ |_, i| i.odd? }.reject{ |c| c.empty? }.map(&:to_s)
159
159
  records = execute_async(queries, arguments).map do |item|
160
160
  # pagination
161
161
  elems = []
162
162
  loop do
163
- item.rows.map { |x| elems << x }
163
+ item.rows.each{ |x| elems << x }
164
164
  break if item.last_page?
165
165
  item = item.next_page
166
166
  end
167
167
  elems
168
168
  end
169
- records.flatten!
169
+ {results: records.flatten!}
170
+ end
171
+
172
+ def select_paginated(scope)
173
+ queries = QueryBuilder.new(self, scope).to_query_async
174
+ queries.compact! if queries.present?
175
+ raise CassandraObject::RecordNotFound if !queries.present?
176
+
177
+ arguments = scope.select_values.select{ |sv| sv != :column1 }.map(&:to_s)
178
+ arguments += scope.where_values.select.each_with_index{ |_, i| i.odd? }.reject{ |c| c.empty? }.map(&:to_s)
179
+ new_next_cursor = nil
180
+ records = []
181
+ execute_async(queries, arguments, scope.limit_value, scope.next_cursor).each do |item|
182
+ new_next_cursor = item.paging_state unless item.last_page?
183
+ item.rows.each{ |x| records << x }
184
+ end
185
+ return {results: records, new_next_cursor: new_next_cursor}
170
186
  end
171
187
 
172
188
  def insert(table, id, attributes, ttl = nil)
@@ -34,13 +34,13 @@ module CassandraObject
34
34
  if klass.respond_to?(method_name)
35
35
  scoping { klass.send(method_name, *args, &block) }
36
36
  elsif Array.method_defined?(method_name)
37
- to_a.send(method_name, *args, &block)
37
+ execute.send(method_name, *args, &block)
38
38
  else
39
39
  super
40
40
  end
41
41
  end
42
42
 
43
- def select_records
43
+ def select_records(auto_paginate = true)
44
44
  results = []
45
45
  records = {}
46
46
  new_next_cursor = nil
@@ -50,24 +50,25 @@ module CassandraObject
50
50
  records[key] = attributes
51
51
  end
52
52
  else
53
- if @is_all
53
+ if @is_all && @id_values.empty?
54
54
  pre = klass.adapter.pre_select(self, @limit_value, @next_cursor)
55
- new_next_cursor = pre[:new_next_cursor]
55
+ new_next_cursor ||= pre[:new_next_cursor]
56
56
  return {results: [], next_cursor: new_next_cursor} if pre[:ids].empty? # fix last query all if ids is empty
57
- self.id_values = pre[:ids]
57
+ @id_values = pre[:ids]
58
58
  end
59
59
 
60
- resp = klass.adapter.select(self)
60
+ resp = auto_paginate ? klass.adapter.select(self) : klass.adapter.select_paginated(self)
61
61
  primary_key_column = klass.adapter.primary_key_column
62
- resp.each do |cql_row|
62
+ new_next_cursor ||= resp[:new_next_cursor]
63
+ resp[:results].each do |cql_row|
63
64
  key = cql_row[primary_key_column]
64
65
  records[key] ||= {}
65
66
  records[key][cql_row.values[1]] = cql_row.values[2]
66
67
  end
67
-
68
68
  end
69
- # limit
69
+
70
70
  records = records.first(@limit_value) if @limit_value.present?
71
+
71
72
  records.each do |key, attributes|
72
73
  if self.raw_response || self.schema_type == :dynamic_attributes
73
74
  results << {key => attributes.values.compact.empty? ? attributes.keys : attributes}
@@ -75,11 +76,12 @@ module CassandraObject
75
76
  results << klass.instantiate(key, attributes)
76
77
  end
77
78
  end
78
- results = results.reduce({}, :merge) if self.schema_type == :dynamic_attributes
79
+ results = results.reduce({}, :merge!) if self.schema_type == :dynamic_attributes
79
80
  if @is_all
80
81
  return {results: results, next_cursor: new_next_cursor}
82
+ else
83
+ return results
81
84
  end
82
- return results
83
85
  end
84
86
 
85
87
  end
@@ -15,16 +15,23 @@ module CassandraObject
15
15
  nil
16
16
  end
17
17
 
18
+ def find_in_batches(id, next_cursor = nil)
19
+ obj = self.clone
20
+ obj.is_all = true
21
+ obj.next_cursor = next_cursor
22
+ obj.where_ids(id).execute_paged
23
+ end
24
+
18
25
  def find_all_in_batches(next_cursor = nil)
19
26
  obj = self.clone
20
27
  obj.is_all = true
21
28
  obj.next_cursor = next_cursor
22
- obj.to_a
29
+ obj.execute
23
30
  end
24
31
 
25
32
  def first
26
33
  return limit(1).find_all_in_batches[:results].first if self.schema_type == :dynamic_attributes || self.schema_type == :schemaless
27
- limit(1).to_a.first
34
+ limit(1).execute.first
28
35
  end
29
36
 
30
37
  private
@@ -33,7 +40,7 @@ module CassandraObject
33
40
  if id.blank?
34
41
  raise CassandraObject::RecordNotFound, "Couldn't find #{self.name} with key #{id.inspect}"
35
42
  elsif self.schema_type == :dynamic_attributes
36
- record = where_ids(id).to_a
43
+ record = where_ids(id).execute
37
44
  raise CassandraObject::RecordNotFound if record.empty?
38
45
  record
39
46
  elsif record = where_ids(id)[0]
@@ -47,7 +54,7 @@ module CassandraObject
47
54
  ids = ids.flatten
48
55
  return [] if ids.empty?
49
56
  ids = ids.compact.map(&:to_s).uniq
50
- where_ids(ids).to_a
57
+ where_ids(ids).execute
51
58
  end
52
59
  end
53
60
  end
@@ -21,7 +21,7 @@ module CassandraObject
21
21
 
22
22
  def select(*values, &block)
23
23
  if block_given?
24
- to_a.select(&block)
24
+ execute.select(&block)
25
25
  else
26
26
  clone.select!(*values)
27
27
  end
@@ -60,10 +60,14 @@ module CassandraObject
60
60
  clone.limit! value
61
61
  end
62
62
 
63
- def to_a
63
+ def execute
64
64
  select_records
65
65
  end
66
66
 
67
+ def execute_paged
68
+ select_records(false)
69
+ end
70
+
67
71
  end
68
72
  end
69
73
  end
@@ -52,4 +52,14 @@ class CassandraObject::CoreTest < CassandraObject::TestCase
52
52
  issue = Issue.create
53
53
  assert issue.inspect =~ /^#<Issue id: \"\w+\", created_at: \".+\", updated_at: \".+\", description: \".+\">$/
54
54
  end
55
+
56
+ test 'inspect schema' do
57
+ issue = IssueSchema.create(title: 'tit', description: 'desc')
58
+ assert issue.inspect =~ /^#<IssueSchema id: \"\w+\", title: \".+\", description: \".+\", created_at: \".+\", updated_at: \".+\">$/
59
+ end
60
+
61
+ test 'inspect dynamic' do
62
+ issue = IssueDynamic.create(key: '1', title: 'tit', dynamic_field1: 'one', dynamic_field2: 'two')
63
+ assert issue.inspect =~ /^{:key=>\".+\", :title=>\".+\", :dynamic_field1=>\".+\", :dynamic_field2=>\".+\"}$/
64
+ end
55
65
  end
@@ -39,10 +39,32 @@ class CassandraObject::FinderMethodsTest < CassandraObject::TestCase
39
39
  second_issue = IssueDynamic.create(key: '2', title: 'tit', dynamic_field1: 'one', dynamic_field2: 'two')
40
40
  res = IssueDynamic.find_all_in_batches
41
41
  reobjected = res[:results].map { |key, val| {key: key }.merge(val) }
42
+ IssueDynamic.delete(['1', '2'])
42
43
 
43
44
  assert_equal [first_issue, second_issue].size, reobjected.size
44
45
  end
45
46
 
47
+ test 'find by key in batches dynamic paged' do
48
+ 100.times.each do |i|
49
+ IssueDynamic.create(key: '1', title: 'tit', "dynamic_field_#{i}" => ['a'])
50
+ IssueDynamic.create(key: '2', title: 'tit', "dynamic_field_#{i}" => ['a'])
51
+ end
52
+
53
+ resp = IssueDynamic.limit(10).find_in_batches('1')
54
+ columns = resp[:results]['1']
55
+ assert_equal 10, columns.size
56
+ assert_equal 'dynamic_field_0', columns.keys.first
57
+
58
+ cursor = resp[:next_cursor]
59
+ resp = IssueDynamic.limit(10).find_in_batches('1', cursor)
60
+ columns = resp[:results]['1']
61
+ assert_equal 10, columns.size
62
+ assert_equal 'dynamic_field_18', columns.keys.first
63
+
64
+ IssueDynamic.delete(['1', '2'])
65
+ end
66
+
67
+
46
68
  test 'find all in batches dynamic paged' do
47
69
 
48
70
  issues = []
@@ -104,9 +126,9 @@ class CassandraObject::FinderMethodsTest < CassandraObject::TestCase
104
126
  test 'where' do
105
127
  # todo make better tests
106
128
  # mono parameter
107
- res1 = Issue.cql_response.where("column1 < 'poi'").to_a
129
+ res1 = Issue.cql_response.where("column1 < 'poi'").execute
108
130
  # bi parameter
109
- res = Issue.cql_response.where('column1 < ?', 'poi').to_a
131
+ res = Issue.cql_response.where('column1 < ?', 'poi').execute
110
132
  end
111
133
 
112
134
  # test 'limit in first' do
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: extendi-cassandra_object
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.5
4
+ version: 1.0.6
5
5
  platform: ruby
6
6
  authors:
7
7
  - Duccio Giovannelli
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2017-05-15 00:00:00.000000000 Z
12
+ date: 2017-06-29 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: activemodel
@@ -200,3 +200,4 @@ signing_key:
200
200
  specification_version: 4
201
201
  summary: Cassandra ActiveModel
202
202
  test_files: []
203
+ has_rdoc: