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,205 +0,0 @@
1
- module Cequel
2
-
3
- #
4
- # Handle to a Cassandra keyspace.
5
- #
6
- class Keyspace
7
-
8
- #
9
- # @api private
10
- # @see Cequel.connect
11
- #
12
- def initialize(configuration={})
13
- configure(configuration)
14
- end
15
-
16
- def connection=(connection)
17
- @connection = connection
18
- end
19
-
20
- def configure(configuration = {})
21
- @configuration = configuration
22
- @hosts = configuration[:host] || configuration[:hosts]
23
- @thrift_options = configuration[:thrift].try(:symbolize_keys) || {}
24
- @keyspace = configuration[:keyspace]
25
- # reset the connections
26
- clear_active_connections!
27
- end
28
-
29
- def logger=(logger)
30
- @logger = logger
31
- end
32
-
33
- def logger
34
- @logger
35
- end
36
-
37
- def slowlog=(slowlog)
38
- @slowlog = slowlog
39
- end
40
-
41
- def slowlog
42
- @slowlog
43
- end
44
-
45
- def slowlog_threshold=(slowlog_threshold)
46
- @slowlog_threshold = slowlog_threshold
47
- end
48
-
49
- def slowlog_threshold
50
- @slowlog_threshold
51
- end
52
-
53
- def with_consistency(consistency)
54
- previous_consistency = default_consistency
55
- Thread.current[consistency_key] = consistency
56
- yield
57
- ensure
58
- Thread.current[consistency_key] = previous_consistency
59
- end
60
-
61
- def default_consistency
62
- Thread.current[consistency_key]
63
- end
64
-
65
- def consistency_key
66
- "Cequel::Keyspace[#{object_id}]#default_consistency"
67
- end
68
-
69
- def connection_pool
70
- return @connection_pool if defined? @connection_pool
71
- if @configuration[:pool]
72
- options = {
73
- :size => @configuration[:pool] || 10,
74
- :timeout => @configuration[:pool_timeout] || 5
75
- }
76
- @connection_pool = ConnectionPool.new(options) do
77
- build_connection
78
- end
79
- else
80
- @connection_pool = nil
81
- end
82
- end
83
-
84
- def connection
85
- @connection ||= build_connection
86
- end
87
-
88
- def clear_active_connections!
89
- remove_instance_variable(:@connection) if defined? @connection
90
- remove_instance_variable(:@connection_pool) if defined? @connection_pool
91
- end
92
-
93
- def with_connection(&block)
94
- if connection_pool
95
- connection_pool.with(&block)
96
- else
97
- yield connection
98
- end
99
- end
100
-
101
- #
102
- # Get DataSet encapsulating a column family in this keyspace
103
- #
104
- # @param column_family_name [Symbol] the name of the column family
105
- # @return [DataSet] a column family
106
- #
107
- def [](column_family_name)
108
- DataSet.new(column_family_name.to_sym, self)
109
- end
110
-
111
- #
112
- # Execute a CQL query in this keyspace.
113
- #
114
- # @param statement [String] CQL string
115
- # @param *bind_vars [Object] values for bind variables
116
- #
117
- def execute(statement, *bind_vars)
118
- log('CQL', statement, *bind_vars) do
119
- with_connection do |conn|
120
- conn.execute(statement, *bind_vars)
121
- end
122
- end
123
- end
124
-
125
- #
126
- # Write data to this keyspace using a CQL query. Will be included the
127
- # current batch operation if one is present.
128
- #
129
- # @param (see #execute)
130
- #
131
- def write(statement, *bind_vars)
132
- if get_batch
133
- get_batch.execute(statement, *bind_vars)
134
- else
135
- execute(statement, *bind_vars)
136
- end
137
- end
138
-
139
- #
140
- # Execute write operations in a batch. Any inserts, updates, and deletes
141
- # inside this method's block will be executed inside a CQL BATCH operation.
142
- #
143
- # @param options [Hash]
144
- # @option options [Fixnum] :auto_apply Automatically send batch to Cassandra after this many statements
145
- #
146
- # @example Perform inserts in a batch
147
- # DB.batch do
148
- # DB[:posts].insert(:id => 1, :title => 'One')
149
- # DB[:posts].insert(:id => 2, :title => 'Two')
150
- # end
151
- #
152
- def batch(options = {})
153
- old_batch = get_batch
154
- new_batch = Batch.new(self, options)
155
- set_batch(new_batch)
156
- yield
157
- new_batch.apply
158
- ensure
159
- set_batch(old_batch)
160
- end
161
-
162
- private
163
-
164
- def build_connection
165
- options = @keyspace ? {:keyspace => @keyspace } : {}
166
- CassandraCQL::Database.new(
167
- @hosts,
168
- options,
169
- @thrift_options
170
- )
171
- end
172
-
173
- def get_batch
174
- ::Thread.current[batch_key]
175
- end
176
-
177
- def set_batch(batch)
178
- ::Thread.current[batch_key] = batch
179
- end
180
-
181
- def batch_key
182
- :"cequel-batch-#{object_id}"
183
- end
184
-
185
- def log(label, statement, *bind_vars)
186
- return yield unless logger || slowlog
187
- response = nil
188
- time = Benchmark.ms { response = yield }
189
- generate_message = proc do
190
- sprintf(
191
- '%s (%dms) %s', label, time.to_i,
192
- CassandraCQL::Statement.sanitize(statement, bind_vars)
193
- )
194
- end
195
- logger.debug(&generate_message) if self.logger
196
- threshold = self.slowlog_threshold || 2000
197
- if slowlog && time >= threshold
198
- slowlog.warn(&generate_message)
199
- end
200
- response
201
- end
202
-
203
- end
204
-
205
- end
@@ -1,49 +0,0 @@
1
- module Cequel
2
-
3
- module Model
4
-
5
- #
6
- # @private
7
- #
8
- class ClassInternals
9
-
10
- attr_accessor :key, :default_scope
11
- attr_reader :columns, :associations, :index_preference
12
- attr_writer :column_family_name
13
-
14
- def initialize(clazz)
15
- @clazz = clazz
16
- @columns, @associations = {}, {}
17
- @index_preference = []
18
- @lock = Monitor.new
19
- end
20
-
21
- def add_column(name, type, options = {})
22
- @columns[name] = Column.new(name, type, options)
23
- end
24
-
25
- def type_column
26
- @columns[:class_name]
27
- end
28
-
29
- def column_family_name
30
- @column_family_name ||= @clazz.name.tableize
31
- end
32
-
33
- def base_class
34
- @clazz
35
- end
36
-
37
- def association(name)
38
- associations[name]
39
- end
40
-
41
- def synchronize(&block)
42
- @lock.synchronize(&block)
43
- end
44
-
45
- end
46
-
47
- end
48
-
49
- end
@@ -1,20 +0,0 @@
1
- module Cequel
2
-
3
- module Model
4
-
5
- #
6
- # Encapsulates information about a column in a model's column family
7
- #
8
- class Column
9
- attr_reader :name, :type, :default
10
-
11
- def initialize(name, type, options = {})
12
- @name, @type = name, type
13
- @default = options[:default]
14
- end
15
-
16
- end
17
-
18
- end
19
-
20
- end
@@ -1,35 +0,0 @@
1
- require 'cequel/model/readable_dictionary'
2
-
3
- module Cequel
4
-
5
- module Model
6
-
7
- class Counter < ReadableDictionary
8
-
9
- def increment(columns_or_deltas, delta = 1)
10
- scope.increment(construct_deltas(columns_or_deltas, delta))
11
- end
12
-
13
- def decrement(columns_or_deltas, delta = 1)
14
- scope.decrement(construct_deltas(columns_or_deltas, delta))
15
- end
16
-
17
- private
18
-
19
- def construct_deltas(columns_or_deltas, delta)
20
- if Hash === columns_or_deltas
21
- columns_or_deltas
22
- else
23
- {}.tap do |deltas|
24
- Array.wrap(columns_or_deltas).each do |column|
25
- deltas[column] = delta
26
- end
27
- end
28
- end
29
- end
30
-
31
- end
32
-
33
- end
34
-
35
- end
@@ -1,126 +0,0 @@
1
- require 'cequel/model/readable_dictionary'
2
-
3
- module Cequel
4
-
5
- module Model
6
-
7
- class Dictionary < ReadableDictionary
8
-
9
- class <<self
10
-
11
- def validation
12
- @validation ||= :text
13
- end
14
-
15
- def maps(options)
16
- @comparator, @validation = *options.first
17
- end
18
-
19
- end
20
-
21
- def each_pair(options = {})
22
- return super if !block_given? || @loaded
23
- new_columns = @changed_columns.dup
24
- super do |column, value|
25
- if @changed_columns.include?(column)
26
- new_columns.delete(column)
27
- yield column, @row[column]
28
- elsif !@deleted_columns.include?(column)
29
- yield column, value
30
- end
31
- end
32
- new_columns.each do |column|
33
- yield column, @row[column]
34
- end
35
- self
36
- end
37
-
38
- def [](column)
39
- if @loaded || @changed_columns.include?(column)
40
- @row[column]
41
- elsif !@deleted_columns.include?(column)
42
- value = super
43
- deserialize_value(column, value) if value
44
- end
45
- end
46
-
47
- def slice(*columns)
48
- super.tap do |slice|
49
- unless @loaded
50
- slice.merge!(@row.slice(*columns))
51
- @deleted_columns.each { |column| slice.delete(column) }
52
- end
53
- end
54
- end
55
-
56
- def []=(column, value)
57
- if value.nil?
58
- @deleted_columns << column
59
- @changed_columns.delete(column)
60
- else
61
- @changed_columns << column
62
- @deleted_columns.delete(column)
63
- end
64
- @row[column] = value
65
- end
66
-
67
- def destroy
68
- scope.delete
69
- setup
70
- end
71
-
72
- def save
73
- batch_size = self.class.default_batch_size
74
- @changed_columns.each_slice(batch_size) do |slice|
75
- updates = {}
76
- slice.each do |column|
77
- updates[column] = serialize_value(@row[column])
78
- end
79
- scope.update(updates) if updates.any?
80
- end
81
- @deleted_columns.each_slice(batch_size) do |slice|
82
- scope.delete(*slice.to_a) if slice.any?
83
- end
84
- @row.clear unless @loaded
85
- @changed_columns.clear
86
- @deleted_columns.clear
87
- self
88
- end
89
-
90
- private
91
-
92
- def setup(init_row = nil)
93
- super
94
- @changed_columns = Set[]
95
- @deleted_columns = Set[]
96
- end
97
-
98
- #
99
- # Subclasses may override this method to implement custom serialization
100
- # strategies
101
- #
102
- def serialize_value(value)
103
- value
104
- end
105
-
106
- #
107
- # Subclasses may override this method to implement custom deserialization
108
- # strategies
109
- #
110
- def deserialize_value(column, value)
111
- value
112
- end
113
-
114
- def deserialize_row(row)
115
- {}.tap do |slice|
116
- row.each_pair do |column, value|
117
- slice[column] = deserialize_value(column, value)
118
- end
119
- end
120
- end
121
-
122
- end
123
-
124
- end
125
-
126
- end
@@ -1,53 +0,0 @@
1
- module Cequel
2
-
3
- module Model
4
-
5
- module Dirty
6
-
7
- extend ActiveSupport::Concern
8
-
9
- included do
10
- include ActiveModel::Dirty
11
- include ChangedAttributesWithIndifferentAccess
12
- end
13
-
14
- module ClassMethods
15
-
16
- def column(name, type, options = {})
17
- define_attribute_method(name)
18
- super
19
- end
20
-
21
- end
22
-
23
- def save
24
- super.tap do
25
- @previously_changed = changes
26
- changed_attributes.clear
27
- end
28
- end
29
-
30
- def _hydrate(row)
31
- super.tap { changed_attributes.clear }
32
- end
33
-
34
- private
35
-
36
- def write_attribute(name, value)
37
- attribute_will_change!(name) if value != read_attribute(name)
38
- super
39
- end
40
-
41
- end
42
-
43
- module ChangedAttributesWithIndifferentAccess
44
-
45
- def changed_attributes
46
- @changed_attributes ||= HashWithIndifferentAccess.new
47
- end
48
-
49
- end
50
-
51
- end
52
-
53
- end