cequel 0.5.6 → 1.0.0.pre.1

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.
Files changed (108) hide show
  1. checksums.yaml +7 -0
  2. data/lib/cequel.rb +5 -8
  3. data/lib/cequel/errors.rb +1 -0
  4. data/lib/cequel/metal.rb +17 -0
  5. data/lib/cequel/metal/batch.rb +62 -0
  6. data/lib/cequel/metal/cql_row_specification.rb +26 -0
  7. data/lib/cequel/metal/data_set.rb +461 -0
  8. data/lib/cequel/metal/deleter.rb +47 -0
  9. data/lib/cequel/metal/incrementer.rb +35 -0
  10. data/lib/cequel/metal/inserter.rb +53 -0
  11. data/lib/cequel/metal/keyspace.rb +213 -0
  12. data/lib/cequel/metal/row.rb +48 -0
  13. data/lib/cequel/metal/row_specification.rb +37 -0
  14. data/lib/cequel/metal/statement.rb +30 -0
  15. data/lib/cequel/metal/updater.rb +65 -0
  16. data/lib/cequel/metal/writer.rb +73 -0
  17. data/lib/cequel/model.rb +12 -84
  18. data/lib/cequel/model/association_collection.rb +23 -0
  19. data/lib/cequel/model/associations.rb +84 -80
  20. data/lib/cequel/model/base.rb +74 -0
  21. data/lib/cequel/model/belongs_to_association.rb +31 -0
  22. data/lib/cequel/model/callbacks.rb +14 -10
  23. data/lib/cequel/model/collection.rb +255 -0
  24. data/lib/cequel/model/errors.rb +6 -6
  25. data/lib/cequel/model/has_many_association.rb +26 -0
  26. data/lib/cequel/model/mass_assignment.rb +31 -0
  27. data/lib/cequel/model/persistence.rb +119 -115
  28. data/lib/cequel/model/properties.rb +89 -87
  29. data/lib/cequel/model/railtie.rb +21 -14
  30. data/lib/cequel/model/record_set.rb +285 -0
  31. data/lib/cequel/model/schema.rb +33 -0
  32. data/lib/cequel/model/scoped.rb +5 -48
  33. data/lib/cequel/model/validations.rb +18 -18
  34. data/lib/cequel/schema.rb +15 -0
  35. data/lib/cequel/schema/column.rb +135 -0
  36. data/lib/cequel/schema/create_table_dsl.rb +56 -0
  37. data/lib/cequel/schema/keyspace.rb +50 -0
  38. data/lib/cequel/schema/table.rb +120 -0
  39. data/lib/cequel/schema/table_property.rb +67 -0
  40. data/lib/cequel/schema/table_reader.rb +139 -0
  41. data/lib/cequel/schema/table_synchronizer.rb +114 -0
  42. data/lib/cequel/schema/table_updater.rb +83 -0
  43. data/lib/cequel/schema/table_writer.rb +80 -0
  44. data/lib/cequel/schema/update_table_dsl.rb +60 -0
  45. data/lib/cequel/type.rb +232 -0
  46. data/lib/cequel/version.rb +1 -1
  47. data/spec/environment.rb +5 -1
  48. data/spec/examples/metal/data_set_spec.rb +608 -0
  49. data/spec/examples/model/associations_spec.rb +84 -74
  50. data/spec/examples/model/callbacks_spec.rb +66 -59
  51. data/spec/examples/model/list_spec.rb +393 -0
  52. data/spec/examples/model/map_spec.rb +229 -0
  53. data/spec/examples/model/mass_assignment_spec.rb +55 -0
  54. data/spec/examples/model/naming_spec.rb +11 -4
  55. data/spec/examples/model/persistence_spec.rb +140 -150
  56. data/spec/examples/model/properties_spec.rb +122 -75
  57. data/spec/examples/model/record_set_spec.rb +285 -0
  58. data/spec/examples/model/schema_spec.rb +44 -0
  59. data/spec/examples/model/serialization_spec.rb +20 -14
  60. data/spec/examples/model/set_spec.rb +133 -0
  61. data/spec/examples/model/spec_helper.rb +0 -10
  62. data/spec/examples/model/validations_spec.rb +51 -38
  63. data/spec/examples/schema/table_reader_spec.rb +328 -0
  64. data/spec/examples/schema/table_synchronizer_spec.rb +172 -0
  65. data/spec/examples/schema/table_updater_spec.rb +157 -0
  66. data/spec/examples/schema/table_writer_spec.rb +225 -0
  67. data/spec/examples/spec_helper.rb +29 -0
  68. data/spec/examples/type_spec.rb +204 -0
  69. data/spec/support/helpers.rb +67 -8
  70. metadata +121 -152
  71. data/lib/cequel/batch.rb +0 -58
  72. data/lib/cequel/cql_row_specification.rb +0 -22
  73. data/lib/cequel/data_set.rb +0 -371
  74. data/lib/cequel/keyspace.rb +0 -205
  75. data/lib/cequel/model/class_internals.rb +0 -49
  76. data/lib/cequel/model/column.rb +0 -20
  77. data/lib/cequel/model/counter.rb +0 -35
  78. data/lib/cequel/model/dictionary.rb +0 -126
  79. data/lib/cequel/model/dirty.rb +0 -53
  80. data/lib/cequel/model/dynamic.rb +0 -31
  81. data/lib/cequel/model/inheritable.rb +0 -48
  82. data/lib/cequel/model/instance_internals.rb +0 -23
  83. data/lib/cequel/model/local_association.rb +0 -42
  84. data/lib/cequel/model/magic.rb +0 -79
  85. data/lib/cequel/model/mass_assignment_security.rb +0 -21
  86. data/lib/cequel/model/naming.rb +0 -17
  87. data/lib/cequel/model/observer.rb +0 -42
  88. data/lib/cequel/model/readable_dictionary.rb +0 -182
  89. data/lib/cequel/model/remote_association.rb +0 -40
  90. data/lib/cequel/model/scope.rb +0 -362
  91. data/lib/cequel/model/subclass_internals.rb +0 -45
  92. data/lib/cequel/model/timestamps.rb +0 -52
  93. data/lib/cequel/model/translation.rb +0 -17
  94. data/lib/cequel/row_specification.rb +0 -63
  95. data/lib/cequel/statement.rb +0 -23
  96. data/spec/examples/data_set_spec.rb +0 -444
  97. data/spec/examples/keyspace_spec.rb +0 -84
  98. data/spec/examples/model/counter_spec.rb +0 -94
  99. data/spec/examples/model/dictionary_spec.rb +0 -301
  100. data/spec/examples/model/dirty_spec.rb +0 -39
  101. data/spec/examples/model/dynamic_spec.rb +0 -41
  102. data/spec/examples/model/inheritable_spec.rb +0 -45
  103. data/spec/examples/model/magic_spec.rb +0 -199
  104. data/spec/examples/model/mass_assignment_security_spec.rb +0 -13
  105. data/spec/examples/model/observer_spec.rb +0 -86
  106. data/spec/examples/model/scope_spec.rb +0 -677
  107. data/spec/examples/model/timestamps_spec.rb +0 -52
  108. data/spec/examples/model/translation_spec.rb +0 -23
@@ -1,40 +0,0 @@
1
- module Cequel
2
-
3
- module Model
4
-
5
- class RemoteAssociation
6
-
7
- attr_reader :name, :class_name, :dependent
8
-
9
- def initialize(name, owning_class, options)
10
- @name, @owning_class = name, owning_class
11
- @class_name = options[:class_name] || name.to_s.classify.to_sym
12
- @foreign_key_name = options[:foreign_key]
13
- @dependent = options[:dependent]
14
- end
15
-
16
- def scope(instance)
17
- clazz.where(foreign_key_name => instance.__send__(primary_key_name))
18
- end
19
-
20
- def primary_key
21
- @primary_key ||= @owning_class.key_column
22
- end
23
-
24
- def primary_key_name
25
- @primary_key_name ||= primary_key.name
26
- end
27
-
28
- def foreign_key_name
29
- @foreign_key_name ||= :"#{@owning_class.name.underscore}_id"
30
- end
31
-
32
- def clazz
33
- @clazz ||= class_name.to_s.constantize
34
- end
35
-
36
- end
37
-
38
- end
39
-
40
- end
@@ -1,362 +0,0 @@
1
- module Cequel
2
-
3
- module Model
4
-
5
- class Scope < BasicObject
6
-
7
- include ::Enumerable
8
-
9
- def initialize(clazz, data_sets)
10
- @clazz, @data_sets = clazz, data_sets
11
- @index_preference_applied = false
12
- end
13
-
14
- def each(&block)
15
- if block
16
- each_row do |row|
17
- result = hydrate(row)
18
- yield result if result
19
- end
20
- else
21
- ::Enumerator.new(self, :each)
22
- end
23
- end
24
-
25
- def each_row(&block)
26
- if block
27
- apply_index_preference!
28
- @data_sets.each do |data_set|
29
- data_set.each(&block)
30
- end
31
- else
32
- ::Enumerator.new(self, :each_row)
33
- end
34
- end
35
-
36
- def find_in_batches(options = {})
37
- unless ::Kernel.block_given?
38
- return ::Enumerator.new(self, :find_in_batches, options)
39
- end
40
- find_rows_in_batches(options) do |batch|
41
- results = batch.map { |row| hydrate(row) }.compact
42
- yield results if results.any?
43
- end
44
- end
45
-
46
- def find_rows_in_batches(options = {}, &block)
47
- return ::Enumerator.new(self, :find_rows_in_batches, options) if block.nil?
48
- batch_size = options[:batch_size] || 1000
49
- apply_index_preference!
50
- @data_sets.each do |data_set|
51
- keys = lookup_keys(data_set)
52
- if keys
53
- find_rows_in_key_batches(data_set, keys, batch_size, &block)
54
- else
55
- find_rows_in_range_batches(data_set, batch_size, &block)
56
- end
57
- end
58
- nil
59
- end
60
-
61
- def find_each(options = {}, &block)
62
- unless ::Kernel.block_given?
63
- return ::Enumerator.new(self, :find_each, options)
64
- end
65
- find_in_batches(options) { |batch| batch.each(&block) }
66
- end
67
-
68
- def find_each_row(options = {}, &block)
69
- unless ::Kernel.block_given?
70
- return ::Enumerator.new(self, :find_each_row, options)
71
- end
72
- find_rows_in_batches(options) { |batch| batch.each(&block) }
73
- end
74
-
75
- def first
76
- apply_index_preference!
77
- @data_sets.each do |data_set|
78
- row = hydrate(data_set.first)
79
- return row if row
80
- end
81
- nil
82
- end
83
-
84
- def count
85
- if restriction_columns == [@clazz.key_alias]
86
- ::Kernel.raise ::Cequel::Model::InvalidQuery,
87
- "Meaningless to perform count with key row restrictions"
88
- end
89
- apply_index_preference!
90
- @data_sets.inject(0) { |count, data_set| count + data_set.count }
91
- end
92
-
93
- def size
94
- count
95
- end
96
-
97
- def length
98
- to_a.length
99
- end
100
-
101
- def update_all(changes)
102
- keys = keys()
103
- unless keys.empty?
104
- @clazz.column_family.where(key_alias => keys).update(changes)
105
- end
106
- end
107
-
108
- def destroy_all
109
- each { |instance| instance.destroy }
110
- end
111
-
112
- def delete_all
113
- if @data_sets.length == 1
114
- if @data_sets.first.row_specifications.length == 0
115
- return @data_sets.first.truncate
116
- end
117
- end
118
- keys = keys()
119
- if keys.empty?
120
- @data_sets.each { |data_set| data_set.delete }
121
- else
122
- @clazz.column_family.where(key_alias => keys).delete
123
- end
124
- end
125
-
126
- def find(*keys, &block)
127
- if block then super
128
- else with_scope(self) { @clazz.find(*keys) }
129
- end
130
- end
131
-
132
- def any?(&block)
133
- if block then super
134
- else count > 0
135
- end
136
- end
137
-
138
- def none?(&block)
139
- if block then super
140
- else empty?
141
- end
142
- end
143
-
144
- def empty?
145
- count == 0
146
- end
147
-
148
- def one?(&block)
149
- if block then super
150
- else count == 1
151
- end
152
- end
153
-
154
- def keys
155
- key_alias = @clazz.key_alias
156
- [].tap do |keys|
157
- @data_sets.each do |data_set|
158
- lookup_keys = lookup_keys(data_set)
159
- if lookup_keys
160
- keys.concat(lookup_keys)
161
- next
162
- end
163
- data_set.select!(key_alias).each { |row| keys << row[key_alias] }
164
- end
165
- end
166
- end
167
-
168
- def lookup_keys(data_set)
169
- if data_set.row_specifications.length == 1
170
- specification = data_set.row_specifications.first
171
- if specification.respond_to?(:column)
172
- if specification.column == key_alias
173
- ::Kernel.Array(specification.value)
174
- end
175
- end
176
- end
177
- end
178
-
179
- def inspect
180
- to_a.inspect
181
- end
182
-
183
- def ==(other)
184
- to_a == other.to_a
185
- end
186
-
187
- def select(*rows, &block)
188
- if block then super
189
- else scoped { |data_set| data_set.select(*rows) }.validate!
190
- end
191
- end
192
-
193
- def select!(*rows)
194
- scoped { |data_set| data_set.select!(*rows) }.validate!
195
- end
196
-
197
- def consistency(consistency)
198
- scoped { |data_set| data_set.consistency(consistency) }
199
- end
200
-
201
- def where(*row_specification)
202
- if row_specification.length == 1 && ::Hash === row_specification.first
203
- row_specification.first.each_pair.inject(self) do |scope, (column, value)|
204
- scope.where_column_equals(column, value)
205
- end
206
- else
207
- scoped { |data_set| data_set.where(*row_specification) }
208
- end
209
- end
210
-
211
- def where!(*row_specification)
212
- scoped { |data_set| data_set.where!(*row_specification) }
213
- end
214
-
215
- def limit(*row_specification)
216
- scoped { |data_set| data_set.limit(*row_specification) }
217
- end
218
-
219
- def scoped(&block)
220
- new_data_sets = @data_sets.map(&block)
221
- Scope.new(@clazz, new_data_sets)
222
- end
223
-
224
- def nil?
225
- false # for ActiveSupport delegation
226
- end
227
-
228
- def method_missing(method, *args, &block)
229
- if @clazz.respond_to?(method)
230
- @clazz.with_scope(self) do
231
- @clazz.__send__(method, *args, &block)
232
- end
233
- else
234
- super
235
- end
236
- end
237
-
238
- protected
239
-
240
- def validate!
241
- columns = restriction_columns
242
- key_column = restriction_columns.include?(@clazz.key_alias)
243
- non_key_column = restriction_columns.any? do |column|
244
- column != @clazz.key_alias
245
- end
246
- if key_column
247
- if non_key_column
248
- ::Kernel.raise InvalidQuery,
249
- "Can't select by key and non-key columns in the same query"
250
- elsif key_only_select?
251
- ::Kernel.raise InvalidQuery,
252
- "Meaningless to select only key column with key row specification"
253
- end
254
- end
255
- self
256
- end
257
-
258
- def where_column_equals(column, value)
259
- if [] == value
260
- Scope.new(@clazz, [])
261
- elsif column.to_sym != @clazz.key_alias && ::Array === value
262
- new_data_sets = []
263
- @data_sets.each do |data_set|
264
- value.each do |element|
265
- new_data_sets << data_set.where(column => element)
266
- end
267
- end
268
- Scope.new(@clazz, new_data_sets)
269
- else
270
- scoped { |data_set| data_set.where(column => value) }
271
- end.validate!
272
- end
273
-
274
- private
275
-
276
- def find_rows_in_range_batches(data_set, batch_size)
277
- key_alias = @clazz.key_alias
278
- key_alias = key_alias.upcase if key_alias =~ /key/i
279
- scope = data_set.limit(batch_size)
280
- unless data_set.select_columns.empty? ||
281
- data_set.select_columns.include?(key_alias)
282
-
283
- scope = scope.select(key_alias)
284
- end
285
-
286
- batch_scope = scope
287
- last_key = nil
288
- begin
289
- batch_rows = batch_scope.to_a
290
- break if batch_rows.empty?
291
- if batch_rows.first[key_alias] == last_key
292
- yield batch_rows[1..-1]
293
- else
294
- yield batch_rows
295
- end
296
- last_key = batch_rows.last[key_alias]
297
- batch_scope =
298
- scope.where("? > ?", key_alias, last_key)
299
- end while batch_rows.length == batch_size
300
- end
301
-
302
- def find_rows_in_key_batches(data_set, keys, batch_size)
303
- key_alias = @clazz.key_alias
304
- keys.each_slice(batch_size) do |key_slice|
305
- yield data_set.where!(key_alias => key_slice).to_a
306
- end
307
- end
308
-
309
- def key_only_select?
310
- key_only_select = @data_sets.all? do |data_set|
311
- data_set.select_columns == [@clazz.key_alias]
312
- end
313
- end
314
-
315
- def restriction_columns
316
- [].tap do |columns|
317
- @data_sets.each do |data_set|
318
- data_set.row_specifications.each do |specification|
319
- if specification.respond_to?(:column)
320
- columns << specification.column
321
- end
322
- end
323
- end
324
- end
325
- end
326
-
327
- def hydrate(row)
328
- return if row.nil?
329
- key_alias = @clazz.key_alias.to_s
330
- key_alias = key_alias.upcase if key_alias =~ /^key$/i
331
- row.reject! { |k, v| v.nil? }
332
- if row.keys.any? && (key_only_select? || row.keys != [key_alias])
333
- @clazz._hydrate(row)
334
- end
335
- end
336
-
337
- def apply_index_preference!
338
- return if @index_preference_applied
339
- # XXX seems ugly to do the in-place sort here.
340
- preference = @clazz.index_preference_columns
341
- @data_sets.each do |data_set|
342
- data_set.row_specifications.sort! do |spec1, spec2|
343
- if spec1.respond_to?(:column) && spec2.respond_to?(:column)
344
- pref1 = preference.index(spec1.column)
345
- pref2 = preference.index(spec2.column)
346
- if pref1 && pref2 then pref1 - pref2
347
- elsif pref1 then -1
348
- elsif pref2 then 1
349
- else 0
350
- end
351
- else 0
352
- end
353
- end
354
- end
355
- @index_preference_applied = true
356
- end
357
-
358
- end
359
-
360
- end
361
-
362
- end
@@ -1,45 +0,0 @@
1
- module Cequel
2
-
3
- module Model
4
-
5
- class SubclassInternals < ClassInternals
6
-
7
- def initialize(clazz, super_internals)
8
- super(clazz)
9
- @super = super_internals
10
- @columns = {}
11
- end
12
-
13
- def index_preference
14
- @super.index_preference + @index_preference
15
- end
16
-
17
- def key
18
- @super.key
19
- end
20
-
21
- def columns
22
- @super.columns.merge(@columns)
23
- end
24
-
25
- def type_column
26
- @super.type_column
27
- end
28
-
29
- def column_family_name
30
- @super.column_family_name
31
- end
32
-
33
- def base_class
34
- @super.base_class
35
- end
36
-
37
- def associations
38
- @super.associations.merge(super)
39
- end
40
-
41
- end
42
-
43
- end
44
-
45
- end
@@ -1,52 +0,0 @@
1
- module Cequel
2
-
3
- module Model
4
-
5
- module Timestamps
6
-
7
- extend ActiveSupport::Concern
8
-
9
- included do
10
- include CreatedAt
11
- include UpdatedAt
12
- end
13
-
14
- module CreatedAt
15
-
16
- extend ActiveSupport::Concern
17
-
18
- included do
19
- column :created_at, :timestamp
20
- before_create :_set_created_at
21
- end
22
-
23
- private
24
-
25
- def _set_created_at
26
- self.created_at = Time.now
27
- end
28
-
29
- end
30
-
31
- module UpdatedAt
32
-
33
- extend ActiveSupport::Concern
34
-
35
- included do
36
- column :updated_at, :timestamp
37
- before_save :_set_updated_at
38
- end
39
-
40
- private
41
-
42
- def _set_updated_at
43
- self.updated_at = Time.now if transient? || changed?
44
- end
45
-
46
- end
47
-
48
- end
49
-
50
- end
51
-
52
- end