cequel 0.5.6 → 1.0.0.pre.1

Sign up to get free protection for your applications and to get access to all the features.
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,31 +0,0 @@
1
- module Cequel
2
-
3
- module Model
4
-
5
- module Dynamic
6
-
7
- def [](column)
8
- read_attribute(column)
9
- end
10
-
11
- def []=(column, value)
12
- write_attribute(column, value)
13
- end
14
-
15
- private
16
-
17
- def attribute_change(attr)
18
- if attribute_changed?(attr)
19
- if respond_to_without_attributes?(attr)
20
- super
21
- else
22
- [changed_attributes[attr], self[attr]]
23
- end
24
- end
25
- end
26
-
27
- end
28
-
29
- end
30
-
31
- end
@@ -1,48 +0,0 @@
1
- module Cequel
2
-
3
- module Model
4
-
5
- module Inheritable
6
-
7
- module SubclassMethods
8
-
9
- extend ActiveSupport::Concern
10
-
11
- module ClassMethods
12
-
13
- def all
14
- super.where(@_cequel.type_column.name => name)
15
- end
16
-
17
- end
18
-
19
- def initialize(*args, &block)
20
- super
21
- __send__("#{self.class.type_column.name}=", self.class.name)
22
- end
23
-
24
- end
25
-
26
- def inherited(subclass)
27
- super
28
- unless @_cequel.type_column
29
- raise ArgumentError,
30
- "Can't subclass model class that does not define a type column"
31
- end
32
- subclass._cequel = SubclassInternals.new(subclass, @_cequel)
33
- subclass.module_eval { include(SubclassMethods) }
34
- end
35
-
36
- def base_class
37
- @_cequel.base_class
38
- end
39
-
40
- protected
41
-
42
- attr_writer :_cequel
43
-
44
- end
45
-
46
- end
47
-
48
- end
@@ -1,23 +0,0 @@
1
- module Cequel
2
-
3
- module Model
4
-
5
- #
6
- # @private
7
- #
8
- class InstanceInternals
9
-
10
- attr_accessor :key, :attributes, :persisted
11
- attr_reader :associations
12
-
13
- def initialize(instance)
14
- @instance = instance
15
- @attributes = ActiveSupport::HashWithIndifferentAccess.new
16
- @associations = {}
17
- end
18
-
19
- end
20
-
21
- end
22
-
23
- end
@@ -1,42 +0,0 @@
1
- module Cequel
2
-
3
- module Model
4
-
5
- class LocalAssociation
6
-
7
- attr_reader :clazz, :name
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
- end
14
-
15
- def primary_key
16
- @primary_key ||= clazz.key_column
17
- end
18
-
19
- def primary_key_name
20
- @primary_key_name ||= primary_key.name
21
- end
22
-
23
- def foreign_key_name
24
- @foreign_key_name ||= :"#{name}_id"
25
- end
26
-
27
- def scope(instance)
28
- clazz.where(primary_key_name => instance.__send__(foreign_key_name))
29
- end
30
-
31
- def clazz
32
- @clazz ||= @class_name.to_s.constantize
33
- end
34
-
35
- def dependent
36
- end
37
-
38
- end
39
-
40
- end
41
-
42
- end
@@ -1,79 +0,0 @@
1
- module Cequel
2
-
3
- module Model
4
-
5
- module Magic
6
-
7
- FIND_BY_PATTERN = /^find_by_(\w+)$/
8
- FIND_ALL_BY_PATTERN = /^find_all_by_(\w+)$/
9
- FIND_OR_CREATE_BY_PATTERN = /^find_or_create_by_(\w+)$/
10
- FIND_OR_INITIALIZE_BY_PATTERN = /^find_or_initialize_by_(\w+)$/
11
-
12
- def self.scope(scope, columns_string, args)
13
- scope.where(extract_row_specifications(columns_string, args))
14
- end
15
-
16
- def self.find_or_create_by(scope, columns_string, args, &block)
17
- find_or_initialize_by(scope, columns_string, args, &block).tap do |instance|
18
- instance.save unless instance.persisted?
19
- end
20
- end
21
-
22
- def self.find_or_initialize_by(scope, columns_string, args, &block)
23
- row_specifications = extract_row_specifications(columns_string, args)
24
- instance = scope.where(row_specifications).first
25
- if instance.nil?
26
- if args.length == 1 && args.first.is_a?(Hash)
27
- attributes = args.first
28
- else
29
- attributes = row_specifications
30
- end
31
- instance = scope.new(attributes, &block)
32
- end
33
- instance
34
- end
35
-
36
- def self.extract_row_specifications(columns_string, args)
37
- columns = columns_string.split('_and_').map { |column| column.to_sym }
38
- if args.length == 1 && args.first.is_a?(Hash)
39
- args.first.symbolize_keys.slice(*columns)
40
- else
41
- if columns.length != args.length
42
- raise ArgumentError,
43
- "wrong number of arguments(#{args.length} for #{columns.length})"
44
- end
45
- Hash[columns.zip(args)]
46
- end
47
- end
48
-
49
- def respond_to?(method, priv = false)
50
- case method
51
- when FIND_BY_PATTERN, FIND_ALL_BY_PATTERN,
52
- FIND_OR_CREATE_BY_PATTERN, FIND_OR_INITIALIZE_BY_PATTERN
53
-
54
- true
55
- else
56
- super
57
- end
58
- end
59
-
60
- def method_missing(method, *args, &block)
61
- case method.to_s
62
- when FIND_BY_PATTERN
63
- Magic.scope(all, $1, args).first
64
- when FIND_ALL_BY_PATTERN
65
- Magic.scope(all, $1, args).to_a
66
- when FIND_OR_CREATE_BY_PATTERN
67
- Magic.find_or_create_by(all, $1, args, &block)
68
- when FIND_OR_INITIALIZE_BY_PATTERN
69
- Magic.find_or_initialize_by(all, $1, args, &block)
70
- else
71
- super
72
- end
73
- end
74
-
75
- end
76
-
77
- end
78
-
79
- end
@@ -1,21 +0,0 @@
1
- module Cequel
2
-
3
- module Model
4
-
5
- module MassAssignmentSecurity
6
-
7
- extend ActiveSupport::Concern
8
-
9
- included do
10
- include ActiveModel::MassAssignmentSecurity
11
- end
12
-
13
- def attributes=(attributes)
14
- super(sanitize_for_mass_assignment(attributes))
15
- end
16
-
17
- end
18
-
19
- end
20
-
21
- end
@@ -1,17 +0,0 @@
1
- module Cequel
2
-
3
- module Model
4
-
5
- module Naming
6
-
7
- extend ActiveSupport::Concern
8
-
9
- included do
10
- include ActiveModel::Naming
11
- end
12
-
13
- end
14
-
15
- end
16
-
17
- end
@@ -1,42 +0,0 @@
1
- module Cequel
2
-
3
- module Model
4
-
5
- #
6
- # This is ripped directly off of ActiveRecord::Observer
7
- #
8
- class Observer < ActiveModel::Observer
9
-
10
- protected
11
-
12
- def observed_classes
13
- klasses = super
14
- klasses + klasses.map { |klass| klass.descendants }.flatten
15
- end
16
-
17
- def add_observer!(klass)
18
- super
19
- define_callbacks klass
20
- end
21
-
22
- def define_callbacks(klass)
23
- observer = self
24
- observer_name = observer.class.name.underscore.gsub('/', '__')
25
-
26
- Cequel::Model::Callbacks::CALLBACKS.each do |callback|
27
- next unless respond_to?(callback)
28
- callback_meth = :"_notify_#{observer_name}_for_#{callback}"
29
- unless klass.respond_to?(callback_meth)
30
- klass.send(:define_method, callback_meth) do |&block|
31
- observer.update(callback, self, &block)
32
- end
33
- klass.send(callback, callback_meth)
34
- end
35
- end
36
- end
37
-
38
- end
39
-
40
- end
41
-
42
- end
@@ -1,182 +0,0 @@
1
- module Cequel
2
-
3
- module Model
4
-
5
- class ReadableDictionary
6
-
7
- class <<self
8
-
9
- attr_writer :column_family, :default_batch_size
10
-
11
- def key_alias
12
- @key_alias ||= :KEY
13
- end
14
-
15
- def key_type
16
- @key_type ||= :text
17
- end
18
-
19
- def comparator
20
- @comparator ||= :text
21
- end
22
-
23
- def validation
24
- :counter
25
- end
26
-
27
- def key(key_alias, type)
28
- @key_alias, @key_type = key_alias, type
29
-
30
- module_eval(<<-RUBY)
31
- def #{key_alias.downcase}
32
- @key
33
- end
34
- RUBY
35
- end
36
-
37
- def columns(comparator)
38
- @comparator = comparator
39
- end
40
-
41
- def column_family
42
- return @column_family if @column_family
43
- self.column_family_name = name.underscore.to_sym
44
- @column_family
45
- end
46
-
47
- def column_family_name=(column_family_name)
48
- self.column_family = Cequel::Model.keyspace[column_family_name]
49
- end
50
-
51
- def default_batch_size
52
- @default_batch_size || 1000
53
- end
54
-
55
- def [](key)
56
- new(key)
57
- end
58
- private :new
59
-
60
- def load(*keys)
61
- keys.flatten!
62
- column_family.
63
- where(key_alias.to_s => keys).
64
- map { |row| new(row.delete(key_alias.to_s), row) }
65
- end
66
-
67
- end
68
-
69
- include Enumerable
70
-
71
- def initialize(key, row = nil)
72
- @key = key
73
- setup(row)
74
- end
75
-
76
- def [](column)
77
- if @loaded
78
- @row[column]
79
- else
80
- scope.select(column).first[column]
81
- end
82
- end
83
-
84
- def keys
85
- @loaded ? @row.keys : each_pair.map { |key, value| key }
86
- end
87
-
88
- def values
89
- @loaded ? @row.values : each_pair.map { |key, value| value }
90
- end
91
-
92
- def slice(*columns)
93
- if @loaded
94
- @row.slice(*columns)
95
- else
96
- deserialize_row(load_raw_slice(columns))
97
- end
98
- end
99
-
100
- def first
101
- @loaded ? @row.first : slice(:first => 1).first
102
- end
103
-
104
- def last
105
- if @loaded
106
- unless @row.empty?
107
- key = @row.keys.last
108
- [key, @row[key]]
109
- end
110
- else
111
- slice(:last => 1).first
112
- end
113
- end
114
-
115
- def key?(column)
116
- @row.key?(column) || load_raw_slice([column])[column].present?
117
- end
118
-
119
- def each_pair(options = {}, &block)
120
- return Enumerator.new(self, :each_pair, options) unless block
121
- return @row.each_pair(&block) if @loaded
122
- batch_size = options[:batch_size] || self.class.default_batch_size
123
- each_slice(batch_size) do |batch_results|
124
- batch_results.each_pair(&block)
125
- end
126
- end
127
-
128
- def each(&block)
129
- each_pair(&block)
130
- end
131
-
132
- def each_slice(batch_size)
133
- batch_scope = scope.select(:first => batch_size)
134
- key_alias = self.class.key_alias
135
- last_key = nil
136
- begin
137
- batch_results = batch_scope.first
138
- batch_results.delete(key_alias)
139
- result_length = batch_results.length
140
- batch_results.delete(last_key) unless last_key.nil?
141
- yield deserialize_row(batch_results)
142
- last_key = batch_results.keys.last
143
- batch_scope = batch_scope.select(:from => last_key)
144
- end while result_length == batch_size
145
- end
146
-
147
- def load
148
- return self if @loaded
149
- @row = {}
150
- each_pair { |column, value| @row[column] = value }
151
- @loaded = true
152
- self
153
- end
154
-
155
- def loaded?
156
- !!@loaded
157
- end
158
-
159
- private
160
-
161
- def setup(init_row = nil)
162
- @row = deserialize_row(init_row || {})
163
- @loaded = !!init_row
164
- end
165
-
166
- def scope
167
- self.class.column_family.where(self.class.key_alias => @key)
168
- end
169
-
170
- def load_raw_slice(columns)
171
- row = scope.select(*columns).first.except(self.class.key_alias)
172
- end
173
-
174
- def deserialize_row(row)
175
- row
176
- end
177
-
178
- end
179
-
180
- end
181
-
182
- end