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
@@ -0,0 +1,74 @@
1
+ module Cequel
2
+
3
+ module Model
4
+
5
+ class Base
6
+
7
+ include Cequel::Model::Properties
8
+ include Cequel::Model::Schema
9
+ include Cequel::Model::Persistence
10
+ include Cequel::Model::Associations
11
+ extend Cequel::Model::Scoped
12
+ include Cequel::Model::MassAssignment
13
+ include Cequel::Model::Callbacks
14
+ include Cequel::Model::Validations
15
+ extend ActiveModel::Naming
16
+ include ActiveModel::Serializers::JSON
17
+ include ActiveModel::Serializers::Xml
18
+
19
+ class_attribute :table_name, :connection, :default_attributes,
20
+ :instance_writer => false
21
+
22
+ def self.inherited(base)
23
+ base.table_name = base.name.tableize.to_sym unless base.name.nil?
24
+ base.default_attributes = {}
25
+ end
26
+
27
+ def self.establish_connection(configuration)
28
+ self.connection = Cequel.connect(configuration)
29
+ end
30
+
31
+ class <<self; alias_method :new_empty, :new; end
32
+ def self.new(*args, &block)
33
+ new_empty.tap do |record|
34
+ record.__send__(:initialize_new_record, *args)
35
+ yield record if block_given?
36
+ end
37
+ end
38
+
39
+ def initialize(&block)
40
+ @attributes, @collection_proxies = {}, {}
41
+ instance_eval(&block) if block
42
+ end
43
+
44
+ def inspect
45
+ inspected_attributes = attributes.each_pair.map do |attr, value|
46
+ inspected_value = value.is_a?(CassandraCQL::UUID) ?
47
+ value.to_guid :
48
+ value.inspect
49
+ "#{attr}: #{inspected_value}"
50
+ end
51
+ "#<#{self.class} #{inspected_attributes.join(", ")}>"
52
+ end
53
+
54
+ protected
55
+ attr_reader :collection_proxies
56
+
57
+ private
58
+
59
+ def initialize_new_record(attributes = {})
60
+ @attributes = Marshal.load(Marshal.dump(default_attributes))
61
+ @new_record = true
62
+ yield self if block_given?
63
+ self.attributes = attributes #XXX this should really be in Properties
64
+ loaded!
65
+ self
66
+ end
67
+
68
+ end
69
+
70
+ end
71
+
72
+ Base = Model::Base
73
+
74
+ end
@@ -0,0 +1,31 @@
1
+ module Cequel
2
+
3
+ module Model
4
+
5
+ class BelongsToAssociation
6
+
7
+ extend Forwardable
8
+
9
+ attr_reader :owner_class, :name, :association_class_name
10
+
11
+ def_delegator :association_class, :key_columns, :association_key_columns
12
+
13
+ def initialize(owner_class, name, options = {})
14
+ @owner_class, @name = owner_class, name.to_sym
15
+ @association_class_name =
16
+ options.fetch(:class_name, @name.to_s.classify)
17
+ end
18
+
19
+ def association_class
20
+ @association_class ||= association_class_name.constantize
21
+ end
22
+
23
+ def instance_variable_name
24
+ @instance_variable_name ||= :"@#{name}"
25
+ end
26
+
27
+ end
28
+
29
+ end
30
+
31
+ end
@@ -6,25 +6,29 @@ module Cequel
6
6
 
7
7
  extend ActiveSupport::Concern
8
8
 
9
- HOOKS = [:save, :create, :update, :destroy, :validation]
10
- CALLBACKS = HOOKS.map { |hook| [:"before_#{hook}", :"after_#{hook}"] }.
11
- flatten
12
-
13
9
  included do
14
10
  extend ActiveModel::Callbacks
15
- define_model_callbacks *HOOKS
11
+ define_model_callbacks :save, :create, :update, :destroy
16
12
  end
17
13
 
18
- def save(*args)
19
- run_callbacks(:save) do
20
- run_callbacks(persisted? ? :update : :create) { super }
21
- end
14
+ def save(options = {})
15
+ run_callbacks(:save) { super }
22
16
  end
23
17
 
24
- def destroy(*args)
18
+ def destroy
25
19
  run_callbacks(:destroy) { super }
26
20
  end
27
21
 
22
+ protected
23
+
24
+ def create
25
+ run_callbacks(:create) { super }
26
+ end
27
+
28
+ def update
29
+ run_callbacks(:update) { super }
30
+ end
31
+
28
32
  end
29
33
 
30
34
  end
@@ -0,0 +1,255 @@
1
+ require 'delegate'
2
+
3
+ module Cequel
4
+
5
+ module Model
6
+
7
+ module Collection
8
+
9
+ extend ActiveSupport::Concern
10
+ extend Forwardable
11
+
12
+ def_delegators :@model, :loaded?, :updater, :deleter
13
+
14
+ attr_reader :column_name
15
+
16
+ included do
17
+ private
18
+ define_method(
19
+ :method_missing,
20
+ BasicObject.instance_method(:method_missing))
21
+ end
22
+
23
+ def initialize(model, column_name)
24
+ @model, @column_name = model, column_name
25
+ end
26
+
27
+ def inspect
28
+ __getobj__.inspect
29
+ end
30
+
31
+ def loaded!
32
+ modifications.each { |modification| modification.() }.clear
33
+ end
34
+
35
+ def persisted!
36
+ modifications.clear
37
+ end
38
+
39
+ protected
40
+
41
+ def __getobj__
42
+ @model.__send__(:read_attribute, @column_name) ||
43
+ @model.__send__(:write_attribute, @column_name, self.class.empty)
44
+ end
45
+
46
+ def __setobj__(obj)
47
+ raise "Attempted to call __setobj__ on read-only delegate!"
48
+ end
49
+
50
+ private
51
+
52
+ def to_modify(&block)
53
+ if loaded? then block.()
54
+ else modifications << block
55
+ end
56
+ self
57
+ end
58
+
59
+ def modifications
60
+ @modifications ||= []
61
+ end
62
+
63
+ end
64
+
65
+ class List < DelegateClass(Array)
66
+
67
+ include Collection
68
+
69
+ NON_ATOMIC_MUTATORS = [
70
+ :collect!,
71
+ :delete_if,
72
+ :fill,
73
+ :flatten!,
74
+ :insert,
75
+ :keep_if,
76
+ :map!,
77
+ :pop,
78
+ :reject!,
79
+ :reverse!,
80
+ :rotate!,
81
+ :select!,
82
+ :shift,
83
+ :shuffle!,
84
+ :slice!,
85
+ :sort!,
86
+ :sort_by!,
87
+ :uniq!
88
+ ]
89
+ NON_ATOMIC_MUTATORS.
90
+ each { |method| undef_method(method) if method_defined? method }
91
+
92
+ def self.empty; []; end
93
+
94
+ def []=(position, *args)
95
+ if Range === position then first, count = position.first, position.count
96
+ else first, count = position, args[-2]
97
+ end
98
+ element = args[-1]
99
+ if first < 0
100
+ raise ArgumentError,
101
+ "Bad index #{position}: CQL lists do not support negative indices"
102
+ end
103
+ if count.nil?
104
+ updater.list_replace(column_name, first, element)
105
+ else
106
+ element = Array.wrap(element)
107
+ count.times do |i|
108
+ if i < element.length
109
+ updater.list_replace(column_name, first+i, element[i])
110
+ else
111
+ deleter.list_remove_at(column_name, first+i)
112
+ end
113
+ end
114
+ end
115
+ to_modify { super }
116
+ end
117
+
118
+ def clear
119
+ deleter.delete_columns(column_name)
120
+ to_modify { super }
121
+ end
122
+
123
+ def concat(array)
124
+ updater.list_append(column_name, array)
125
+ to_modify { super }
126
+ end
127
+
128
+ def delete(object)
129
+ updater.list_remove(column_name, object)
130
+ to_modify { super }
131
+ end
132
+
133
+ def delete_at(index)
134
+ deleter.list_remove_at(column_name, index)
135
+ to_modify { super }
136
+ end
137
+
138
+ def push(object)
139
+ updater.list_append(column_name, object)
140
+ to_modify { super }
141
+ end
142
+ alias_method :<<, :push
143
+
144
+ def replace(array)
145
+ updater.set(column_name => array)
146
+ to_modify { super }
147
+ end
148
+
149
+ def unshift(*objs)
150
+ updater.list_prepend(column_name, objs.reverse)
151
+ to_modify { super }
152
+ end
153
+
154
+ end
155
+
156
+ class Set < DelegateClass(::Set)
157
+
158
+ include Collection
159
+
160
+ NON_ATOMIC_MUTATORS = [
161
+ :add?,
162
+ :collect!,
163
+ :delete?,
164
+ :delete_if,
165
+ :flatten!,
166
+ :keep_if,
167
+ :map!,
168
+ :reject!,
169
+ :select!
170
+ ]
171
+ NON_ATOMIC_MUTATORS.
172
+ each { |method| undef_method(method) if method_defined? method }
173
+
174
+ def add(object)
175
+ updater.set_add(column_name, object)
176
+ to_modify { super }
177
+ end
178
+
179
+ def clear
180
+ deleter.delete_columns(column_name)
181
+ to_modify { super }
182
+ end
183
+
184
+ def delete(object)
185
+ updater.set_remove(column_name, object)
186
+ to_modify { super }
187
+ end
188
+
189
+ def replace(set)
190
+ updater.set(column_name => set)
191
+ to_modify { super }
192
+ end
193
+
194
+ end
195
+
196
+ class Map < DelegateClass(::Hash)
197
+
198
+ include Collection
199
+
200
+ NON_ATOMIC_MUTATORS = [
201
+ :default,
202
+ :default=,
203
+ :default_proc,
204
+ :default_proc=,
205
+ :delete_if,
206
+ :deep_merge!,
207
+ :except!,
208
+ :extract!,
209
+ :keep_if,
210
+ :reject!,
211
+ :reverse_merge!,
212
+ :reverse_update,
213
+ :select!,
214
+ :shift,
215
+ :slice!,
216
+ :stringify_keys!,
217
+ :symbolize_keys!,
218
+ :to_options!,
219
+ :transform_keys!
220
+ ]
221
+ NON_ATOMIC_MUTATORS.
222
+ each { |method| undef_method(method) if method_defined? method }
223
+
224
+ def []=(key, value)
225
+ updater.map_update(column_name, key => value)
226
+ to_modify { super }
227
+ end
228
+ alias_method :store, :[]=
229
+
230
+ def clear
231
+ deleter.delete_columns(column_name)
232
+ to_modify { super }
233
+ end
234
+
235
+ def delete(key)
236
+ deleter.map_remove(column_name, key)
237
+ to_modify { super }
238
+ end
239
+
240
+ def merge!(hash)
241
+ updater.map_update(column_name, hash)
242
+ to_modify { super }
243
+ end
244
+ alias_method :update, :merge!
245
+
246
+ def replace(hash)
247
+ updater.set(column_name => hash)
248
+ to_modify { super }
249
+ end
250
+
251
+ end
252
+
253
+ end
254
+
255
+ end
@@ -1,12 +1,12 @@
1
1
  module Cequel
2
-
2
+
3
3
  module Model
4
4
 
5
- Error = Class.new(Cequel::Error)
6
- RecordNotFound = Class.new(Error)
7
- RecordInvalid = Class.new(Error)
8
- MissingKey = Class.new(Error)
9
- InvalidQuery = Class.new(Error)
5
+ MissingAttributeError = Class.new(ArgumentError)
6
+ UnknownAttributeError = Class.new(ArgumentError)
7
+ RecordNotFound = Class.new(StandardError)
8
+ InvalidRecordConfiguration = Class.new(StandardError)
9
+ RecordInvalid = Class.new(StandardError)
10
10
 
11
11
  end
12
12
 
@@ -0,0 +1,26 @@
1
+ module Cequel
2
+
3
+ module Model
4
+
5
+ class HasManyAssociation
6
+
7
+ attr_reader :owner_class, :name, :association_class_name
8
+
9
+ def initialize(owner_class, name, options = {})
10
+ @owner_class, @name = owner_class, name
11
+ @association_class_name = options.fetch(:class_name, name.to_s.classify)
12
+ end
13
+
14
+ def association_class
15
+ @association_class ||= association_class_name.constantize
16
+ end
17
+
18
+ def instance_variable_name
19
+ @instance_variable_name ||= :"@#{name}"
20
+ end
21
+
22
+ end
23
+
24
+ end
25
+
26
+ end