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.
- checksums.yaml +7 -0
- data/lib/cequel.rb +5 -8
- data/lib/cequel/errors.rb +1 -0
- data/lib/cequel/metal.rb +17 -0
- data/lib/cequel/metal/batch.rb +62 -0
- data/lib/cequel/metal/cql_row_specification.rb +26 -0
- data/lib/cequel/metal/data_set.rb +461 -0
- data/lib/cequel/metal/deleter.rb +47 -0
- data/lib/cequel/metal/incrementer.rb +35 -0
- data/lib/cequel/metal/inserter.rb +53 -0
- data/lib/cequel/metal/keyspace.rb +213 -0
- data/lib/cequel/metal/row.rb +48 -0
- data/lib/cequel/metal/row_specification.rb +37 -0
- data/lib/cequel/metal/statement.rb +30 -0
- data/lib/cequel/metal/updater.rb +65 -0
- data/lib/cequel/metal/writer.rb +73 -0
- data/lib/cequel/model.rb +12 -84
- data/lib/cequel/model/association_collection.rb +23 -0
- data/lib/cequel/model/associations.rb +84 -80
- data/lib/cequel/model/base.rb +74 -0
- data/lib/cequel/model/belongs_to_association.rb +31 -0
- data/lib/cequel/model/callbacks.rb +14 -10
- data/lib/cequel/model/collection.rb +255 -0
- data/lib/cequel/model/errors.rb +6 -6
- data/lib/cequel/model/has_many_association.rb +26 -0
- data/lib/cequel/model/mass_assignment.rb +31 -0
- data/lib/cequel/model/persistence.rb +119 -115
- data/lib/cequel/model/properties.rb +89 -87
- data/lib/cequel/model/railtie.rb +21 -14
- data/lib/cequel/model/record_set.rb +285 -0
- data/lib/cequel/model/schema.rb +33 -0
- data/lib/cequel/model/scoped.rb +5 -48
- data/lib/cequel/model/validations.rb +18 -18
- data/lib/cequel/schema.rb +15 -0
- data/lib/cequel/schema/column.rb +135 -0
- data/lib/cequel/schema/create_table_dsl.rb +56 -0
- data/lib/cequel/schema/keyspace.rb +50 -0
- data/lib/cequel/schema/table.rb +120 -0
- data/lib/cequel/schema/table_property.rb +67 -0
- data/lib/cequel/schema/table_reader.rb +139 -0
- data/lib/cequel/schema/table_synchronizer.rb +114 -0
- data/lib/cequel/schema/table_updater.rb +83 -0
- data/lib/cequel/schema/table_writer.rb +80 -0
- data/lib/cequel/schema/update_table_dsl.rb +60 -0
- data/lib/cequel/type.rb +232 -0
- data/lib/cequel/version.rb +1 -1
- data/spec/environment.rb +5 -1
- data/spec/examples/metal/data_set_spec.rb +608 -0
- data/spec/examples/model/associations_spec.rb +84 -74
- data/spec/examples/model/callbacks_spec.rb +66 -59
- data/spec/examples/model/list_spec.rb +393 -0
- data/spec/examples/model/map_spec.rb +229 -0
- data/spec/examples/model/mass_assignment_spec.rb +55 -0
- data/spec/examples/model/naming_spec.rb +11 -4
- data/spec/examples/model/persistence_spec.rb +140 -150
- data/spec/examples/model/properties_spec.rb +122 -75
- data/spec/examples/model/record_set_spec.rb +285 -0
- data/spec/examples/model/schema_spec.rb +44 -0
- data/spec/examples/model/serialization_spec.rb +20 -14
- data/spec/examples/model/set_spec.rb +133 -0
- data/spec/examples/model/spec_helper.rb +0 -10
- data/spec/examples/model/validations_spec.rb +51 -38
- data/spec/examples/schema/table_reader_spec.rb +328 -0
- data/spec/examples/schema/table_synchronizer_spec.rb +172 -0
- data/spec/examples/schema/table_updater_spec.rb +157 -0
- data/spec/examples/schema/table_writer_spec.rb +225 -0
- data/spec/examples/spec_helper.rb +29 -0
- data/spec/examples/type_spec.rb +204 -0
- data/spec/support/helpers.rb +67 -8
- metadata +121 -152
- data/lib/cequel/batch.rb +0 -58
- data/lib/cequel/cql_row_specification.rb +0 -22
- data/lib/cequel/data_set.rb +0 -371
- data/lib/cequel/keyspace.rb +0 -205
- data/lib/cequel/model/class_internals.rb +0 -49
- data/lib/cequel/model/column.rb +0 -20
- data/lib/cequel/model/counter.rb +0 -35
- data/lib/cequel/model/dictionary.rb +0 -126
- data/lib/cequel/model/dirty.rb +0 -53
- data/lib/cequel/model/dynamic.rb +0 -31
- data/lib/cequel/model/inheritable.rb +0 -48
- data/lib/cequel/model/instance_internals.rb +0 -23
- data/lib/cequel/model/local_association.rb +0 -42
- data/lib/cequel/model/magic.rb +0 -79
- data/lib/cequel/model/mass_assignment_security.rb +0 -21
- data/lib/cequel/model/naming.rb +0 -17
- data/lib/cequel/model/observer.rb +0 -42
- data/lib/cequel/model/readable_dictionary.rb +0 -182
- data/lib/cequel/model/remote_association.rb +0 -40
- data/lib/cequel/model/scope.rb +0 -362
- data/lib/cequel/model/subclass_internals.rb +0 -45
- data/lib/cequel/model/timestamps.rb +0 -52
- data/lib/cequel/model/translation.rb +0 -17
- data/lib/cequel/row_specification.rb +0 -63
- data/lib/cequel/statement.rb +0 -23
- data/spec/examples/data_set_spec.rb +0 -444
- data/spec/examples/keyspace_spec.rb +0 -84
- data/spec/examples/model/counter_spec.rb +0 -94
- data/spec/examples/model/dictionary_spec.rb +0 -301
- data/spec/examples/model/dirty_spec.rb +0 -39
- data/spec/examples/model/dynamic_spec.rb +0 -41
- data/spec/examples/model/inheritable_spec.rb +0 -45
- data/spec/examples/model/magic_spec.rb +0 -199
- data/spec/examples/model/mass_assignment_security_spec.rb +0 -13
- data/spec/examples/model/observer_spec.rb +0 -86
- data/spec/examples/model/scope_spec.rb +0 -677
- data/spec/examples/model/timestamps_spec.rb +0 -52
- data/spec/examples/model/translation_spec.rb +0 -23
@@ -0,0 +1,31 @@
|
|
1
|
+
begin
|
2
|
+
require 'active_model/forbidden_attributes_protection'
|
3
|
+
rescue LoadError
|
4
|
+
require 'active_model/mass_assignment_security'
|
5
|
+
end
|
6
|
+
|
7
|
+
module Cequel
|
8
|
+
|
9
|
+
module Model
|
10
|
+
|
11
|
+
module MassAssignment
|
12
|
+
|
13
|
+
extend ActiveSupport::Concern
|
14
|
+
|
15
|
+
included do
|
16
|
+
if defined? ActiveModel::ForbiddenAttributesProtection
|
17
|
+
include ActiveModel::ForbiddenAttributesProtection
|
18
|
+
else
|
19
|
+
include ActiveModel::MassAssignmentSecurity
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
def attributes=(attributes)
|
24
|
+
super(sanitize_for_mass_assignment(attributes))
|
25
|
+
end
|
26
|
+
|
27
|
+
end
|
28
|
+
|
29
|
+
end
|
30
|
+
|
31
|
+
end
|
@@ -8,170 +8,174 @@ module Cequel
|
|
8
8
|
|
9
9
|
module ClassMethods
|
10
10
|
|
11
|
-
delegate :update_all, :destroy_all, :delete_all, :to => :all
|
12
|
-
|
13
|
-
def index_preference(*columns)
|
14
|
-
@_cequel.index_preference.concat(columns.map { |c| c.to_sym })
|
15
|
-
end
|
16
|
-
|
17
|
-
def index_preference_columns
|
18
|
-
@_cequel.index_preference
|
19
|
-
end
|
20
|
-
|
21
|
-
def find(*keys)
|
22
|
-
coerce_array = keys.first.is_a?(Array)
|
23
|
-
keys.flatten!
|
24
|
-
if keys.length == 1
|
25
|
-
instance = find_one(keys.first)
|
26
|
-
coerce_array ? [instance] : instance
|
27
|
-
else
|
28
|
-
find_many(keys)
|
29
|
-
end
|
30
|
-
end
|
31
|
-
|
32
11
|
def create(attributes = {}, &block)
|
33
|
-
new(attributes, &block).tap { |
|
12
|
+
new(attributes, &block).tap { |record| record.save }
|
34
13
|
end
|
35
14
|
|
36
|
-
def
|
37
|
-
|
15
|
+
def hydrate(row)
|
16
|
+
new_empty { hydrate(row) }
|
38
17
|
end
|
39
18
|
|
40
|
-
|
41
|
-
@_cequel.column_family_name = name
|
42
|
-
end
|
19
|
+
end
|
43
20
|
|
44
|
-
|
45
|
-
|
46
|
-
|
21
|
+
def key_attributes
|
22
|
+
@attributes.slice(*self.class.key_column_names)
|
23
|
+
end
|
47
24
|
|
48
|
-
|
49
|
-
|
50
|
-
|
25
|
+
def key_values
|
26
|
+
key_attributes.values
|
27
|
+
end
|
28
|
+
|
29
|
+
def exists?
|
30
|
+
load!
|
31
|
+
true
|
32
|
+
rescue Cequel::Model::RecordNotFound
|
33
|
+
false
|
34
|
+
end
|
35
|
+
alias :exist? :exists?
|
51
36
|
|
52
|
-
|
53
|
-
|
37
|
+
def load
|
38
|
+
unless loaded?
|
39
|
+
row = metal_scope.first
|
40
|
+
hydrate(row) unless row.nil?
|
41
|
+
collection_proxies.each_value { |collection| collection.loaded! }
|
54
42
|
end
|
43
|
+
self
|
44
|
+
end
|
55
45
|
|
56
|
-
|
57
|
-
|
58
|
-
if
|
59
|
-
|
60
|
-
|
61
|
-
clazz = self
|
46
|
+
def load!
|
47
|
+
load.tap do
|
48
|
+
if transient?
|
49
|
+
raise Cequel::Model::RecordNotFound,
|
50
|
+
"Couldn't find #{self.class.name} with #{key_attributes.inspect}"
|
62
51
|
end
|
63
|
-
clazz.allocate._hydrate(row.except(:type))
|
64
52
|
end
|
53
|
+
end
|
65
54
|
|
66
|
-
|
55
|
+
def loaded?(column = nil)
|
56
|
+
!!@loaded && (column.nil? || @attributes.key?(column.to_sym))
|
57
|
+
end
|
67
58
|
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
"Couldn't find #{name} with #{key_alias}=#{key}"
|
73
|
-
end
|
74
|
-
end
|
59
|
+
def save(options = {})
|
60
|
+
options.assert_valid_keys
|
61
|
+
if new_record? then create
|
62
|
+
else update
|
75
63
|
end
|
64
|
+
@new_record = false
|
65
|
+
true
|
66
|
+
end
|
76
67
|
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
68
|
+
def update_attributes(attributes)
|
69
|
+
self.attributes = attributes
|
70
|
+
save
|
71
|
+
end
|
81
72
|
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
results
|
88
|
-
end
|
73
|
+
def destroy
|
74
|
+
metal_scope.delete
|
75
|
+
transient!
|
76
|
+
self
|
77
|
+
end
|
89
78
|
|
79
|
+
def new_record?
|
80
|
+
!!@new_record
|
90
81
|
end
|
91
82
|
|
92
|
-
def
|
93
|
-
persisted
|
83
|
+
def persisted?
|
84
|
+
!!@persisted
|
94
85
|
end
|
95
86
|
|
96
|
-
def
|
97
|
-
|
98
|
-
save
|
87
|
+
def transient?
|
88
|
+
!persisted?
|
99
89
|
end
|
100
90
|
|
101
|
-
|
102
|
-
|
91
|
+
protected
|
92
|
+
|
93
|
+
def persisted!
|
94
|
+
@persisted = true
|
103
95
|
end
|
104
96
|
|
105
|
-
def
|
106
|
-
|
107
|
-
|
108
|
-
|
97
|
+
def transient!
|
98
|
+
@persisted = false
|
99
|
+
end
|
100
|
+
|
101
|
+
def create
|
102
|
+
inserter.execute
|
103
|
+
loaded!
|
109
104
|
persisted!
|
110
105
|
end
|
111
106
|
|
112
107
|
def update
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
delete_attributes << attr
|
118
|
-
else
|
119
|
-
update_attributes[attr] = new
|
120
|
-
end
|
108
|
+
connection.batch do
|
109
|
+
updater.execute
|
110
|
+
deleter.execute
|
111
|
+
@updater, @deleter = nil
|
121
112
|
end
|
122
|
-
data_set.update(update_attributes) if update_attributes.any?
|
123
|
-
data_set.delete(*delete_attributes) if delete_attributes.any?
|
124
|
-
transient! if @_cequel.attributes.empty?
|
125
113
|
end
|
126
114
|
|
127
|
-
def
|
128
|
-
|
115
|
+
def inserter
|
116
|
+
@inserter ||= metal_scope.inserter
|
129
117
|
end
|
130
118
|
|
131
|
-
def
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
end
|
138
|
-
_hydrate(result)
|
139
|
-
self
|
119
|
+
def updater
|
120
|
+
@updater ||= metal_scope.updater
|
121
|
+
end
|
122
|
+
|
123
|
+
def deleter
|
124
|
+
@deleter ||= metal_scope.deleter
|
140
125
|
end
|
141
126
|
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
127
|
+
private
|
128
|
+
|
129
|
+
def read_attribute(attribute)
|
130
|
+
super
|
131
|
+
rescue MissingAttributeError
|
132
|
+
load
|
133
|
+
super
|
134
|
+
end
|
135
|
+
|
136
|
+
def write_attribute(attribute, value)
|
137
|
+
super.tap do
|
138
|
+
if !persisted?
|
139
|
+
inserter.insert(attribute => value) unless value.nil?
|
140
|
+
elsif !self.class.key_column_names.include?(attribute.to_sym)
|
141
|
+
if value.nil?
|
142
|
+
deleter.delete_columns(attribute)
|
143
|
+
else
|
144
|
+
updater.set(attribute => value)
|
145
|
+
end
|
146
|
+
end
|
150
147
|
end
|
151
148
|
end
|
152
149
|
|
153
|
-
def
|
154
|
-
@
|
150
|
+
def hydrate(row)
|
151
|
+
@attributes = row
|
152
|
+
loaded!
|
153
|
+
persisted!
|
154
|
+
self
|
155
155
|
end
|
156
156
|
|
157
|
-
def
|
158
|
-
@
|
157
|
+
def loaded!
|
158
|
+
@loaded = true
|
159
|
+
collection_proxies.each_value { |collection| collection.loaded! }
|
159
160
|
end
|
160
161
|
|
161
|
-
def
|
162
|
-
|
162
|
+
def metal_scope
|
163
|
+
connection[table_name].
|
164
|
+
where(key_attributes)
|
163
165
|
end
|
164
166
|
|
165
|
-
def
|
166
|
-
|
167
|
+
def attributes_for_create
|
168
|
+
@attributes.each_with_object({}) do |(column, value), attributes|
|
169
|
+
attributes[column] = value unless value.nil?
|
170
|
+
end
|
167
171
|
end
|
168
172
|
|
169
|
-
|
173
|
+
def attributes_for_update
|
174
|
+
@attributes_for_update ||= {}
|
175
|
+
end
|
170
176
|
|
171
|
-
def
|
172
|
-
|
173
|
-
self.class.column_family.
|
174
|
-
where(self.class.key_alias => @_cequel.key)
|
177
|
+
def attributes_for_deletion
|
178
|
+
@attributes_for_deletion ||= []
|
175
179
|
end
|
176
180
|
|
177
181
|
end
|
@@ -6,134 +6,136 @@ module Cequel
|
|
6
6
|
|
7
7
|
extend ActiveSupport::Concern
|
8
8
|
|
9
|
-
included do
|
10
|
-
include ActiveModel::Conversion
|
11
|
-
end
|
12
|
-
|
13
9
|
module ClassMethods
|
14
10
|
|
15
|
-
|
16
|
-
key_alias = key_alias.to_sym
|
17
|
-
@_cequel.key = Column.new(key_alias, type)
|
11
|
+
protected
|
18
12
|
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
13
|
+
def key(name, type)
|
14
|
+
def_accessors(name)
|
15
|
+
table_schema.add_key(name, type)
|
16
|
+
set_attribute_default(name, nil)
|
17
|
+
end
|
23
18
|
|
24
|
-
|
25
|
-
|
26
|
-
|
19
|
+
def column(name, type, options = {})
|
20
|
+
def_accessors(name)
|
21
|
+
table_schema.add_data_column(name, type, options[:index])
|
22
|
+
set_attribute_default(name, options[:default])
|
23
|
+
end
|
27
24
|
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
25
|
+
def list(name, type, options = {})
|
26
|
+
def_collection_accessors(name, List)
|
27
|
+
table_schema.add_list(name, type)
|
28
|
+
set_attribute_default(name, options.fetch(:default, []))
|
32
29
|
end
|
33
30
|
|
34
|
-
def
|
35
|
-
name
|
36
|
-
|
31
|
+
def set(name, type, options = {})
|
32
|
+
def_collection_accessors(name, Set)
|
33
|
+
table_schema.add_set(name, type)
|
34
|
+
set_attribute_default(name, options.fetch(:default, ::Set[]))
|
35
|
+
end
|
37
36
|
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
37
|
+
def map(name, key_type, value_type, options = {})
|
38
|
+
def_collection_accessors(name, Map)
|
39
|
+
table_schema.add_map(name, key_type, value_type)
|
40
|
+
set_attribute_default(name, options.fetch(:default, {}))
|
41
|
+
end
|
42
42
|
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
RUBY
|
43
|
+
def table_property(name, value)
|
44
|
+
table_schema.add_property(name, value)
|
45
|
+
end
|
47
46
|
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
end
|
47
|
+
private
|
48
|
+
|
49
|
+
def def_accessors(name)
|
50
|
+
name = name.to_sym
|
51
|
+
def_reader(name)
|
52
|
+
def_writer(name)
|
55
53
|
end
|
56
54
|
|
57
|
-
def
|
58
|
-
|
55
|
+
def def_reader(name)
|
56
|
+
module_eval <<-RUBY
|
57
|
+
def #{name}; read_attribute(#{name.inspect}); end
|
58
|
+
RUBY
|
59
59
|
end
|
60
60
|
|
61
|
-
def
|
62
|
-
|
61
|
+
def def_writer(name)
|
62
|
+
module_eval <<-RUBY
|
63
|
+
def #{name}=(value); write_attribute(#{name.inspect}, value); end
|
64
|
+
RUBY
|
63
65
|
end
|
64
66
|
|
65
|
-
def
|
66
|
-
|
67
|
+
def def_collection_accessors(name, collection_proxy_class)
|
68
|
+
def_collection_reader(name, collection_proxy_class)
|
69
|
+
def_collection_writer(name)
|
67
70
|
end
|
68
71
|
|
69
|
-
def
|
70
|
-
|
72
|
+
def def_collection_reader(name, collection_proxy_class)
|
73
|
+
module_eval <<-RUBY
|
74
|
+
def #{name}
|
75
|
+
proxy_collection(#{name.inspect}, #{collection_proxy_class})
|
76
|
+
end
|
77
|
+
RUBY
|
78
|
+
end
|
79
|
+
|
80
|
+
def def_collection_writer(name)
|
81
|
+
module_eval <<-RUBY
|
82
|
+
def #{name}=(value)
|
83
|
+
reset_collection_proxy(#{name.inspect})
|
84
|
+
write_attribute(#{name.inspect}, value)
|
85
|
+
end
|
86
|
+
RUBY
|
71
87
|
end
|
72
88
|
|
73
|
-
def
|
74
|
-
|
89
|
+
def set_attribute_default(name, default)
|
90
|
+
default_attributes[name.to_sym] = default
|
75
91
|
end
|
76
92
|
|
77
93
|
end
|
78
94
|
|
79
|
-
def
|
80
|
-
|
81
|
-
@_cequel.key = generate_key
|
82
|
-
self.class.columns.each do |column|
|
83
|
-
default = column.default
|
84
|
-
@_cequel.attributes[column.name] = default unless default.nil?
|
85
|
-
end
|
86
|
-
self.attributes = attributes
|
87
|
-
yield self if block_given?
|
95
|
+
def attribute_names
|
96
|
+
@attributes.keys
|
88
97
|
end
|
89
98
|
|
90
99
|
def attributes
|
91
|
-
{
|
92
|
-
|
100
|
+
attribute_names.each_with_object({}) do |name, attributes|
|
101
|
+
attributes[name] = read_attribute(name)
|
102
|
+
end
|
93
103
|
end
|
94
104
|
|
95
105
|
def attributes=(attributes)
|
96
|
-
attributes.each_pair do |
|
97
|
-
__send__("#{
|
106
|
+
attributes.each_pair do |attribute, value|
|
107
|
+
__send__(:"#{attribute}=", value)
|
98
108
|
end
|
99
109
|
end
|
100
110
|
|
101
|
-
|
102
|
-
|
103
|
-
self_key = self.__send__(self.class.key_column.name)
|
104
|
-
other_key = other.__send__(self.class.key_column.name)
|
105
|
-
self_key && other_key && self_key == other_key
|
106
|
-
end
|
111
|
+
protected
|
112
|
+
delegate :table_schema, :to => 'self.class'
|
107
113
|
|
108
|
-
def
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
end
|
116
|
-
inspected << " #{column}:#{inspected_value}"
|
117
|
-
end
|
114
|
+
def read_attribute(name)
|
115
|
+
@attributes.fetch(name)
|
116
|
+
rescue KeyError
|
117
|
+
if table_schema.column(name)
|
118
|
+
raise MissingAttributeError, "missing attribute: #{name}"
|
119
|
+
else
|
120
|
+
raise UnknownAttributeError, "unknown attribute: #{name}"
|
118
121
|
end
|
119
122
|
end
|
120
123
|
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
else
|
127
|
-
@_cequel.attributes[column_name] = value
|
128
|
-
end
|
124
|
+
def write_attribute(name, value)
|
125
|
+
column = table_schema.column(name)
|
126
|
+
raise UnknownAttributeError,
|
127
|
+
"unknown attribute: #{name}" unless column
|
128
|
+
@attributes[name] = value.nil? ? nil : column.cast(value)
|
129
129
|
end
|
130
130
|
|
131
|
-
|
132
|
-
|
131
|
+
private
|
132
|
+
|
133
|
+
def proxy_collection(name, proxy_class)
|
134
|
+
collection_proxies[name] ||= proxy_class.new(self, name)
|
133
135
|
end
|
134
136
|
|
135
|
-
def
|
136
|
-
|
137
|
+
def reset_collection_proxy(name)
|
138
|
+
collection_proxies.delete(name)
|
137
139
|
end
|
138
140
|
|
139
141
|
end
|