cequel 1.0.0.pre.4 → 1.0.0.pre.5
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/cequel/errors.rb +1 -0
- data/lib/cequel/record.rb +1 -0
- data/lib/cequel/record/bound.rb +101 -0
- data/lib/cequel/record/collection.rb +34 -8
- data/lib/cequel/record/persistence.rb +23 -3
- data/lib/cequel/record/properties.rb +8 -10
- data/lib/cequel/record/record_set.rb +55 -37
- data/lib/cequel/schema/column.rb +4 -0
- data/lib/cequel/schema/table_reader.rb +3 -3
- data/lib/cequel/type.rb +23 -17
- data/lib/cequel/version.rb +1 -1
- data/spec/examples/record/list_spec.rb +51 -0
- data/spec/examples/record/map_spec.rb +57 -0
- data/spec/examples/record/persistence_spec.rb +64 -0
- data/spec/examples/record/properties_spec.rb +19 -5
- data/spec/examples/record/record_set_spec.rb +126 -9
- data/spec/examples/record/schema_spec.rb +4 -0
- data/spec/examples/record/set_spec.rb +29 -0
- data/spec/examples/schema/table_reader_spec.rb +2 -2
- data/spec/support/helpers.rb +18 -0
- metadata +3 -2
data/lib/cequel/schema/column.rb
CHANGED
@@ -57,7 +57,7 @@ module Cequel
|
|
57
57
|
unless comparators
|
58
58
|
table.compact_storage = true
|
59
59
|
return unless column_data.empty?
|
60
|
-
column_aliases <<
|
60
|
+
column_aliases << :column1 if column_aliases.empty?
|
61
61
|
comparators = [table_data['comparator']]
|
62
62
|
end
|
63
63
|
column_aliases.zip(comparators) do |column_alias, type|
|
@@ -66,7 +66,7 @@ module Cequel
|
|
66
66
|
clustering_order = :desc
|
67
67
|
end
|
68
68
|
table.add_clustering_column(
|
69
|
-
column_alias.
|
69
|
+
column_alias.to_sym,
|
70
70
|
Type.lookup_internal(type),
|
71
71
|
clustering_order
|
72
72
|
)
|
@@ -76,7 +76,7 @@ module Cequel
|
|
76
76
|
def read_data_columns
|
77
77
|
if column_data.empty?
|
78
78
|
table.add_data_column(
|
79
|
-
table_data['value_alias'],
|
79
|
+
(table_data['value_alias'] || :value).to_sym,
|
80
80
|
Type.lookup_internal(table_data['default_validator']),
|
81
81
|
false
|
82
82
|
)
|
data/lib/cequel/type.rb
CHANGED
@@ -58,18 +58,18 @@ module Cequel
|
|
58
58
|
|
59
59
|
class String < Base
|
60
60
|
|
61
|
-
|
62
|
-
|
63
|
-
def ensure_encoding(value, encoding)
|
64
|
-
str = value.to_s
|
61
|
+
def cast(value)
|
62
|
+
str = String(value)
|
65
63
|
str.encoding.name == encoding ? str : str.dup.force_encoding(encoding)
|
66
64
|
end
|
67
65
|
|
68
66
|
end
|
69
67
|
|
70
68
|
class Ascii < String
|
71
|
-
|
72
|
-
|
69
|
+
private
|
70
|
+
|
71
|
+
def encoding
|
72
|
+
'US-ASCII'
|
73
73
|
end
|
74
74
|
end
|
75
75
|
register Ascii.instance
|
@@ -81,10 +81,14 @@ module Cequel
|
|
81
81
|
end
|
82
82
|
|
83
83
|
def cast(value)
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
84
|
+
value = value.to_s(16) if Integer === value
|
85
|
+
super
|
86
|
+
end
|
87
|
+
|
88
|
+
private
|
89
|
+
|
90
|
+
def encoding
|
91
|
+
'ASCII-8BIT'
|
88
92
|
end
|
89
93
|
|
90
94
|
end
|
@@ -104,7 +108,7 @@ module Cequel
|
|
104
108
|
end
|
105
109
|
|
106
110
|
def cast(value)
|
107
|
-
value
|
111
|
+
Integer(value)
|
108
112
|
end
|
109
113
|
|
110
114
|
end
|
@@ -112,14 +116,14 @@ module Cequel
|
|
112
116
|
|
113
117
|
class Decimal < Base
|
114
118
|
def cast(value)
|
115
|
-
BigDecimal.new(value, 0)
|
119
|
+
BigDecimal === value ? value : BigDecimal.new(value, 0)
|
116
120
|
end
|
117
121
|
end
|
118
122
|
register Decimal.instance
|
119
123
|
|
120
124
|
class Double < Base
|
121
125
|
def cast(value)
|
122
|
-
value
|
126
|
+
Float(value)
|
123
127
|
end
|
124
128
|
end
|
125
129
|
register Double.instance
|
@@ -140,7 +144,7 @@ module Cequel
|
|
140
144
|
end
|
141
145
|
|
142
146
|
def cast(value)
|
143
|
-
value
|
147
|
+
Integer(value)
|
144
148
|
end
|
145
149
|
|
146
150
|
end
|
@@ -168,8 +172,10 @@ module Cequel
|
|
168
172
|
[:varchar]
|
169
173
|
end
|
170
174
|
|
171
|
-
|
172
|
-
|
175
|
+
private
|
176
|
+
|
177
|
+
def encoding
|
178
|
+
'UTF-8'
|
173
179
|
end
|
174
180
|
|
175
181
|
end
|
@@ -186,7 +192,7 @@ module Cequel
|
|
186
192
|
elsif value.respond_to?(:to_time) then value.to_time
|
187
193
|
elsif Numeric === value then Time.at(value)
|
188
194
|
else Time.parse(value.to_s)
|
189
|
-
end
|
195
|
+
end.utc
|
190
196
|
end
|
191
197
|
|
192
198
|
end
|
data/lib/cequel/version.rb
CHANGED
@@ -5,6 +5,7 @@ describe Cequel::Record::List do
|
|
5
5
|
key :permalink, :text
|
6
6
|
column :title, :text
|
7
7
|
list :tags, :text
|
8
|
+
list :contributor_ids, :int
|
8
9
|
end
|
9
10
|
|
10
11
|
let(:scope) { cequel[:posts].where(:permalink => 'cequel') }
|
@@ -14,6 +15,7 @@ describe Cequel::Record::List do
|
|
14
15
|
Post.new do |post|
|
15
16
|
post.permalink = 'cequel'
|
16
17
|
post.tags = %w(one two)
|
18
|
+
post.contributor_ids = [1, 2]
|
17
19
|
end.tap(&:save)
|
18
20
|
end
|
19
21
|
|
@@ -27,6 +29,20 @@ describe Cequel::Record::List do
|
|
27
29
|
end
|
28
30
|
end
|
29
31
|
|
32
|
+
context 'updating' do
|
33
|
+
it 'should overwrite value' do
|
34
|
+
post.tags = %w(three four)
|
35
|
+
post.save!
|
36
|
+
subject[:tags].should == %w(three four)
|
37
|
+
end
|
38
|
+
|
39
|
+
it 'should cast collection before overwriting' do
|
40
|
+
post.tags = Set['three', 'four']
|
41
|
+
post.save!
|
42
|
+
subject[:tags].should == %w(three four)
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
30
46
|
describe '#<<' do
|
31
47
|
it 'should add new items' do
|
32
48
|
post.tags << 'three' << 'four'
|
@@ -52,6 +68,11 @@ describe Cequel::Record::List do
|
|
52
68
|
unloaded_post.tags << 'four' << 'five'
|
53
69
|
unloaded_post.tags.should == %w(one two four five)
|
54
70
|
end
|
71
|
+
|
72
|
+
it 'should cast to defined value' do
|
73
|
+
post.contributor_ids << '3' << 4.0
|
74
|
+
post.contributor_ids.should == [1, 2, 3, 4]
|
75
|
+
end
|
55
76
|
end
|
56
77
|
|
57
78
|
describe '#[]=' do
|
@@ -64,6 +85,11 @@ describe Cequel::Record::List do
|
|
64
85
|
post.tags.should == %w(one TWO)
|
65
86
|
end
|
66
87
|
|
88
|
+
it 'should cast element before replacing' do
|
89
|
+
post.contributor_ids[1] = '5'
|
90
|
+
post.contributor_ids.should == [1, 5]
|
91
|
+
end
|
92
|
+
|
67
93
|
it 'should replace an element without reading' do
|
68
94
|
cequel.should_not_receive :execute
|
69
95
|
unloaded_post.tags[1] = 'TWO'
|
@@ -87,6 +113,11 @@ describe Cequel::Record::List do
|
|
87
113
|
post.tags.should == %w(One Two)
|
88
114
|
end
|
89
115
|
|
116
|
+
it 'should cast multiple elements before replacing them' do
|
117
|
+
post.contributor_ids[0, 2] = %w(4 5)
|
118
|
+
post.contributor_ids.should == [4, 5]
|
119
|
+
end
|
120
|
+
|
90
121
|
it 'should remove elements beyond positional arguments' do
|
91
122
|
scope.list_append(:tags, 'four')
|
92
123
|
post.tags[0, 3] = 'ONE'
|
@@ -151,6 +182,11 @@ describe Cequel::Record::List do
|
|
151
182
|
post.tags.should == %w(one two four five)
|
152
183
|
end
|
153
184
|
|
185
|
+
it 'should cast elements before concatentating' do
|
186
|
+
post.contributor_ids.concat(%w(3 4))
|
187
|
+
post.contributor_ids.should == [1, 2, 3, 4]
|
188
|
+
end
|
189
|
+
|
154
190
|
it 'should concat elements without loading' do
|
155
191
|
cequel.should_not_receive :execute
|
156
192
|
unloaded_post.tags.concat(['four', 'five'])
|
@@ -178,6 +214,11 @@ describe Cequel::Record::List do
|
|
178
214
|
post.tags.should == %w(one)
|
179
215
|
end
|
180
216
|
|
217
|
+
it 'should cast argument' do
|
218
|
+
post.contributor_ids.delete('2')
|
219
|
+
post.contributor_ids.should == [1]
|
220
|
+
end
|
221
|
+
|
181
222
|
it 'should delete without loading' do
|
182
223
|
cequel.should_not_receive :execute
|
183
224
|
unloaded_post.tags.delete('two')
|
@@ -292,6 +333,11 @@ describe Cequel::Record::List do
|
|
292
333
|
post.tags.should == %w(four five)
|
293
334
|
end
|
294
335
|
|
336
|
+
it 'should cast before overwriting' do
|
337
|
+
post.contributor_ids.replace(%w(3 4 5))
|
338
|
+
post.contributor_ids.should == [3, 4, 5]
|
339
|
+
end
|
340
|
+
|
295
341
|
it 'should overwrite without reading' do
|
296
342
|
cequel.should_not_receive :execute
|
297
343
|
unloaded_post.tags.replace(%w(four five))
|
@@ -374,6 +420,11 @@ describe Cequel::Record::List do
|
|
374
420
|
post.tags.should == %w(minustwo minusone one two)
|
375
421
|
end
|
376
422
|
|
423
|
+
it 'should cast element before unshifting' do
|
424
|
+
post.contributor_ids.unshift('0')
|
425
|
+
post.contributor_ids.should == [0, 1, 2]
|
426
|
+
end
|
427
|
+
|
377
428
|
it 'should unshift without reading' do
|
378
429
|
cequel.should_not_receive :execute
|
379
430
|
unloaded_post.tags.unshift('minustwo', 'minusone')
|
@@ -27,6 +27,20 @@ describe Cequel::Record::Map do
|
|
27
27
|
end
|
28
28
|
end
|
29
29
|
|
30
|
+
context 'updating' do
|
31
|
+
it 'should overwrite value' do
|
32
|
+
post.likes = {'charlotte' => 3, 'dave' => 4}
|
33
|
+
post.save!
|
34
|
+
subject[:likes].should == {'charlotte' => 3, 'dave' => 4}
|
35
|
+
end
|
36
|
+
|
37
|
+
it 'should cast collection before overwriting' do
|
38
|
+
post.likes = [['charlotte', 3], ['dave', 4]]
|
39
|
+
post.save!
|
40
|
+
subject[:likes].should == {'charlotte' => 3, 'dave' => 4}
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
30
44
|
describe 'atomic modification' do
|
31
45
|
before { scope.map_update(:likes, 'charles' => 3) }
|
32
46
|
|
@@ -39,6 +53,16 @@ describe Cequel::Record::Map do
|
|
39
53
|
post.likes.should == {'alice' => 1, 'bob' => 2, 'david' => 4}
|
40
54
|
end
|
41
55
|
|
56
|
+
it 'should cast keys when updating' do
|
57
|
+
post.likes[:david] = 4
|
58
|
+
post.likes.should == {'alice' => 1, 'bob' => 2, 'david' => 4}
|
59
|
+
end
|
60
|
+
|
61
|
+
it 'should cast values when updating' do
|
62
|
+
post.likes['david'] = 4.0
|
63
|
+
post.likes.should == {'alice' => 1, 'bob' => 2, 'david' => 4}
|
64
|
+
end
|
65
|
+
|
42
66
|
it 'should write without reading' do
|
43
67
|
max_statements! 2
|
44
68
|
unloaded_post.likes['david'] = 4
|
@@ -83,6 +107,11 @@ describe Cequel::Record::Map do
|
|
83
107
|
post.likes.should == {'alice' => 1}
|
84
108
|
end
|
85
109
|
|
110
|
+
it 'should cast key before deleting' do
|
111
|
+
post.likes.delete(:bob)
|
112
|
+
post.likes.should == {'alice' => 1}
|
113
|
+
end
|
114
|
+
|
86
115
|
it 'should delete without reading' do
|
87
116
|
max_statements! 2
|
88
117
|
unloaded_post.likes.delete('bob')
|
@@ -106,6 +135,22 @@ describe Cequel::Record::Map do
|
|
106
135
|
{'alice' => 1, 'bob' => 2, 'david' => 4, 'emily' => 5}
|
107
136
|
end
|
108
137
|
|
138
|
+
it 'should cast keys before updating' do
|
139
|
+
post.likes.merge!(david: 4, emily: 5)
|
140
|
+
post.save
|
141
|
+
post.likes.should ==
|
142
|
+
{'alice' => 1, 'bob' => 2, 'david' => 4, 'emily' => 5}
|
143
|
+
end
|
144
|
+
|
145
|
+
it 'should cast values before updating' do
|
146
|
+
post.likes.merge!('david' => '4', 'emily' => 5.0)
|
147
|
+
post.save
|
148
|
+
subject[:likes].should ==
|
149
|
+
{'alice' => 1, 'bob' => 2, 'charles' => 3, 'david' => 4, 'emily' => 5}
|
150
|
+
post.likes.should ==
|
151
|
+
{'alice' => 1, 'bob' => 2, 'david' => 4, 'emily' => 5}
|
152
|
+
end
|
153
|
+
|
109
154
|
it 'should write without reading' do
|
110
155
|
max_statements! 2
|
111
156
|
unloaded_post.likes.merge!('david' => 4, 'emily' => 5)
|
@@ -129,6 +174,18 @@ describe Cequel::Record::Map do
|
|
129
174
|
post.likes.should == {'david' => 4, 'emily' => 5}
|
130
175
|
end
|
131
176
|
|
177
|
+
it 'should cast keys before overwriting' do
|
178
|
+
post.likes.replace(david: 4, emily: 5)
|
179
|
+
post.likes.should == {'david' => 4, 'emily' => 5}
|
180
|
+
end
|
181
|
+
|
182
|
+
it 'should cast values before overwriting' do
|
183
|
+
post.likes.replace('david' => '4', 'emily' => 5.0)
|
184
|
+
post.save
|
185
|
+
subject[:likes].should == {'david' => 4, 'emily' => 5}
|
186
|
+
post.likes.should == {'david' => 4, 'emily' => 5}
|
187
|
+
end
|
188
|
+
|
132
189
|
it 'should overwrite without reading' do
|
133
190
|
max_statements! 2
|
134
191
|
unloaded_post.likes.replace('david' => 4, 'emily' => 5)
|
@@ -36,6 +36,12 @@ describe Cequel::Record::Persistence do
|
|
36
36
|
it 'should mark row persisted' do
|
37
37
|
blog.should be_persisted
|
38
38
|
end
|
39
|
+
|
40
|
+
it 'should fail fast if keys are missing' do
|
41
|
+
expect {
|
42
|
+
Blog.new.save
|
43
|
+
}.to raise_error(Cequel::MissingKeyError)
|
44
|
+
end
|
39
45
|
end
|
40
46
|
|
41
47
|
context 'on update' do
|
@@ -59,6 +65,13 @@ describe Cequel::Record::Persistence do
|
|
59
65
|
it 'should remove old column values' do
|
60
66
|
subject[:description].should be_nil
|
61
67
|
end
|
68
|
+
|
69
|
+
it 'should not allow changing key values' do
|
70
|
+
expect {
|
71
|
+
blog.subdomain = 'soup'
|
72
|
+
blog.save
|
73
|
+
}.to raise_error(ArgumentError)
|
74
|
+
end
|
62
75
|
end
|
63
76
|
end
|
64
77
|
|
@@ -80,6 +93,14 @@ describe Cequel::Record::Persistence do
|
|
80
93
|
it 'should save instance' do
|
81
94
|
Blog.find(blog.subdomain).name.should == 'Big Data'
|
82
95
|
end
|
96
|
+
|
97
|
+
it 'should fail fast if keys are missing' do
|
98
|
+
expect {
|
99
|
+
Blog.create do |blog|
|
100
|
+
blog.name = 'Big Data'
|
101
|
+
end
|
102
|
+
}.to raise_error(Cequel::MissingKeyError)
|
103
|
+
end
|
83
104
|
end
|
84
105
|
|
85
106
|
describe 'with attributes' do
|
@@ -94,6 +115,12 @@ describe Cequel::Record::Persistence do
|
|
94
115
|
it 'should save instance' do
|
95
116
|
Blog.find(blog.subdomain).name.should == 'Big Data'
|
96
117
|
end
|
118
|
+
|
119
|
+
it 'should fail fast if keys are missing' do
|
120
|
+
expect {
|
121
|
+
Blog.create(:name => 'Big Data')
|
122
|
+
}.to raise_error(Cequel::MissingKeyError)
|
123
|
+
end
|
97
124
|
end
|
98
125
|
end
|
99
126
|
|
@@ -111,6 +138,11 @@ describe Cequel::Record::Persistence do
|
|
111
138
|
it 'should save instance' do
|
112
139
|
Blog.find(blog.subdomain).name.should == 'The Big Data Blog'
|
113
140
|
end
|
141
|
+
|
142
|
+
it 'should not allow updating key values' do
|
143
|
+
expect { blog.update_attributes(:subdomain => 'soup') }
|
144
|
+
.to raise_error(ArgumentError)
|
145
|
+
end
|
114
146
|
end
|
115
147
|
|
116
148
|
describe '#destroy' do
|
@@ -150,6 +182,24 @@ describe Cequel::Record::Persistence do
|
|
150
182
|
it 'should mark row persisted' do
|
151
183
|
post.should be_persisted
|
152
184
|
end
|
185
|
+
|
186
|
+
it 'should fail fast if parent keys are missing' do
|
187
|
+
expect {
|
188
|
+
Post.new do |post|
|
189
|
+
post.permalink = 'cequel'
|
190
|
+
post.title = 'Cequel'
|
191
|
+
end.tap(&:save)
|
192
|
+
}.to raise_error(Cequel::MissingKeyError)
|
193
|
+
end
|
194
|
+
|
195
|
+
it 'should fail fast if row keys are missing' do
|
196
|
+
expect {
|
197
|
+
Post.new do |post|
|
198
|
+
post.blog_subdomain = 'cassandra'
|
199
|
+
post.title = 'Cequel'
|
200
|
+
end.tap(&:save)
|
201
|
+
}.to raise_error(Cequel::MissingKeyError)
|
202
|
+
end
|
153
203
|
end
|
154
204
|
|
155
205
|
context 'on update' do
|
@@ -173,6 +223,20 @@ describe Cequel::Record::Persistence do
|
|
173
223
|
it 'should remove old column values' do
|
174
224
|
subject[:body].should be_nil
|
175
225
|
end
|
226
|
+
|
227
|
+
it 'should not allow changing parent key values' do
|
228
|
+
expect {
|
229
|
+
post.blog_subdomain = 'soup'
|
230
|
+
post.save
|
231
|
+
}.to raise_error(ArgumentError)
|
232
|
+
end
|
233
|
+
|
234
|
+
it 'should not allow changing row key values' do
|
235
|
+
expect {
|
236
|
+
post.permalink = 'soup-recipes'
|
237
|
+
post.save
|
238
|
+
}.to raise_error(ArgumentError)
|
239
|
+
end
|
176
240
|
end
|
177
241
|
end
|
178
242
|
|