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.
@@ -18,6 +18,10 @@ module Cequel
18
18
  false
19
19
  end
20
20
 
21
+ def type?(type_in)
22
+ type.is_a?(type_in)
23
+ end
24
+
21
25
  def clustering_column?
22
26
  false
23
27
  end
@@ -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 << nil if column_aliases.empty?
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.try(:to_sym),
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
- private
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
- def cast(value)
72
- ensure_encoding(value, 'US-ASCII')
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
- case value
85
- when Integer then ensure_encoding(value.to_s(16), 'ASCII-8BIT')
86
- else ensure_encoding(value.to_s, 'ASCII-8BIT')
87
- end
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.to_i
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.to_f
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.to_i
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
- def cast(value)
172
- ensure_encoding(value, 'UTF-8')
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
@@ -1,3 +1,3 @@
1
1
  module Cequel
2
- VERSION = '1.0.0.pre.4'
2
+ VERSION = '1.0.0.pre.5'
3
3
  end
@@ -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