cequel 1.0.0.pre.4 → 1.0.0.pre.5

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.
@@ -61,11 +61,15 @@ describe Cequel::Record::Properties do
61
61
  should == %w(one two three)
62
62
  end
63
63
 
64
- it 'should cast values in list column' do
65
- Post.new { |post| post.tags = Set[1, 2, 3] }.tags.
64
+ it 'should cast collection in list column to list' do
65
+ Post.new { |post| post.tags = Set['1', '2', '3'] }.tags.
66
66
  should == %w(1 2 3)
67
67
  end
68
68
 
69
+ it 'should cast elements in list' do
70
+ Post.new { |post| post.tags = [1, 2, 3] }.tags.should == %w(1 2 3)
71
+ end
72
+
69
73
  it 'should have empty list column value if unset' do
70
74
  Post.new.tags.should == []
71
75
  end
@@ -75,8 +79,13 @@ describe Cequel::Record::Properties do
75
79
  categories.should == Set['Big Data', 'Cassandra']
76
80
  end
77
81
 
78
- it 'should cast values to correct type' do
79
- Post.new { |post| post.categories = [1, 2, 3] }.categories.
82
+ it 'should cast values in set column to correct type' do
83
+ Post.new { |post| post.categories = Set[1, 2, 3] }.categories.
84
+ should == Set['1', '2', '3']
85
+ end
86
+
87
+ it 'should cast collection to set in set column' do
88
+ Post.new { |post| post.categories = ['1', '2', '3'] }.categories.
80
89
  should == Set['1', '2', '3']
81
90
  end
82
91
 
@@ -90,7 +99,12 @@ describe Cequel::Record::Properties do
90
99
  end
91
100
 
92
101
  it 'should cast values for map column' do
93
- Post.new { |post| post.shares = [[:facebook, '1'], [:twitter, '2']] }.
102
+ Post.new { |post| post.shares = {facebook: '1', twitter: '2'} }.
103
+ shares.should == {'facebook' => 1, 'twitter' => 2}
104
+ end
105
+
106
+ it 'should cast collection passed to map column to map' do
107
+ Post.new { |post| post.shares = [['facebook', 1], ['twitter', 2]] }.
94
108
  shares.should == {'facebook' => 1, 'twitter' => 2}
95
109
  end
96
110
 
@@ -2,18 +2,18 @@ require File.expand_path('../spec_helper', __FILE__)
2
2
 
3
3
  describe Cequel::Record::RecordSet do
4
4
  model :Blog do
5
- key :subdomain, :text
5
+ key :subdomain, :ascii
6
6
  column :name, :text
7
7
  column :description, :text
8
8
  end
9
9
 
10
10
  model :Post do
11
- key :blog_subdomain, :text
12
- key :permalink, :text
11
+ key :blog_subdomain, :ascii
12
+ key :permalink, :ascii
13
13
  column :title, :text
14
14
  column :body, :text
15
- column :author_id, :uuid, :index => true
16
- column :author_name, :text, :index => true
15
+ column :author_id, :uuid, index: true
16
+ column :author_name, :text, index: true
17
17
  list :tags, :text
18
18
  set :categories, :text
19
19
  map :shares, :text, :int
@@ -23,8 +23,22 @@ describe Cequel::Record::RecordSet do
23
23
  end
24
24
  end
25
25
 
26
+ model :Comment do
27
+ key :blog_subdomain, :text
28
+ key :permalink, :text
29
+ key :id, :uuid, :auto => true
30
+ column :body, :text
31
+ end
32
+
33
+ model :PublishedPost do
34
+ key :blog_subdomain, :ascii
35
+ key :published_at, :timeuuid
36
+ column :permalink, :ascii, index: true
37
+ end
38
+
26
39
  let(:subdomains) { [] }
27
40
  let(:uuids) { Array.new(2) { CassandraCQL::UUID.new }}
41
+ let(:now) { Time.at(Time.now.to_i) }
28
42
 
29
43
  before do
30
44
  cequel.batch do
@@ -35,8 +49,7 @@ describe Cequel::Record::RecordSet do
35
49
  blog.description = "This is Blog number #{i}"
36
50
  end.save
37
51
  end
38
- end
39
- cequel.batch do
52
+
40
53
  5.times do |i|
41
54
  cequel[:posts].insert(
42
55
  :blog_subdomain => 'cassandra',
@@ -45,12 +58,26 @@ describe Cequel::Record::RecordSet do
45
58
  :body => "Post number #{i}",
46
59
  :author_id => uuids[i%2]
47
60
  )
61
+ cequel[:published_posts].insert(
62
+ :blog_subdomain => 'cassandra',
63
+ :published_at => max_uuid(now + (i - 4).minutes),
64
+ :permalink => "cequel#{i}"
65
+ )
48
66
  cequel[:posts].insert(
49
67
  :blog_subdomain => 'postgres',
50
68
  :permalink => "sequel#{i}",
51
69
  :title => "Sequel #{i}"
52
70
  )
53
71
  end
72
+
73
+ 5.times do |i|
74
+ cequel[:comments].insert(
75
+ :blog_subdomain => 'cassandra',
76
+ :permalink => 'cequel0',
77
+ :id => CassandraCQL::UUID.new(Time.now - 5 + i),
78
+ :body => "Comment #{i}"
79
+ )
80
+ end
54
81
  end
55
82
  end
56
83
 
@@ -66,7 +93,11 @@ describe Cequel::Record::RecordSet do
66
93
  specify { Blog.new.should_not be_persisted }
67
94
  specify { Blog.new.should be_transient }
68
95
 
69
- specify do
96
+ it 'should cast argument to correct type' do
97
+ Blog.find('blog-0'.force_encoding('ASCII-8BIT')).should be
98
+ end
99
+
100
+ it 'should raise RecordNotFound if bad argument passed' do
70
101
  expect { Blog.find('bogus') }.
71
102
  to raise_error(Cequel::Record::RecordNotFound)
72
103
  end
@@ -84,7 +115,12 @@ describe Cequel::Record::RecordSet do
84
115
  specify { Post.new.should_not be_persisted }
85
116
  specify { Post.new.should be_transient }
86
117
 
87
- specify do
118
+ it 'should cast all keys to correct type' do
119
+ Post['cassandra'.force_encoding('ASCII-8BIT')].
120
+ find('cequel0'.force_encoding('ASCII-8BIT')).should be
121
+ end
122
+
123
+ it 'should raise RecordNotFound if bad argument passed' do
88
124
  expect { Post['cequel'].find('bogus')}.
89
125
  to raise_error(Cequel::Record::RecordNotFound)
90
126
  end
@@ -109,6 +145,10 @@ describe Cequel::Record::RecordSet do
109
145
  disallow_queries!
110
146
  subject.description.should == 'This is Blog number 0'
111
147
  end
148
+
149
+ it 'should cast argument' do
150
+ subject.subdomain.encoding.name.should == 'US-ASCII'
151
+ end
112
152
  end
113
153
 
114
154
  context 'compound primary key' do
@@ -120,6 +160,11 @@ describe Cequel::Record::RecordSet do
120
160
  subject.permalink.should == 'cequel0'
121
161
  end
122
162
 
163
+ it 'should cast all keys to the correct type' do
164
+ subject.blog_subdomain.encoding.name.should == 'US-ASCII'
165
+ subject.permalink.encoding.name.should == 'US-ASCII'
166
+ end
167
+
123
168
  it 'should lazily query the database when attribute accessed' do
124
169
  subject.title.should == 'Cequel 0'
125
170
  end
@@ -155,6 +200,12 @@ describe Cequel::Record::RecordSet do
155
200
  Post.at('cassandra').find_each(:batch_size => 2).map(&:title).
156
201
  should == (0...5).map { |i| "Cequel #{i}" }
157
202
  end
203
+
204
+ it 'should cast arguments correctly' do
205
+ Post.at('cassandra'.force_encoding('ASCII-8BIT')).
206
+ find_each(:batch_size => 2).map(&:title).
207
+ should == (0...5).map { |i| "Cequel #{i}" }
208
+ end
158
209
  end
159
210
 
160
211
  describe '#[]' do
@@ -176,6 +227,16 @@ describe Cequel::Record::RecordSet do
176
227
  Post.at('cassandra').after('cequel1').map(&:title).
177
228
  should == (2...5).map { |i| "Cequel #{i}" }
178
229
  end
230
+
231
+ it 'should cast argument' do
232
+ Post.at('cassandra').after('cequel1'.force_encoding('ASCII-8BIT')).
233
+ map(&:title).should == (2...5).map { |i| "Cequel #{i}" }
234
+ end
235
+
236
+ it 'should query Time range for Timeuuid key' do
237
+ PublishedPost['cassandra'].after(now - 3.minutes).map(&:permalink).
238
+ should == %w(cequel2 cequel3 cequel4)
239
+ end
179
240
  end
180
241
 
181
242
  describe '#from' do
@@ -184,6 +245,16 @@ describe Cequel::Record::RecordSet do
184
245
  should == (1...5).map { |i| "Cequel #{i}" }
185
246
  end
186
247
 
248
+ it 'should cast argument' do
249
+ Post.at('cassandra').from('cequel1'.force_encoding('ASCII-8BIT')).
250
+ map(&:title).should == (1...5).map { |i| "Cequel #{i}" }
251
+ end
252
+
253
+ it 'should query Time range for Timeuuid key' do
254
+ PublishedPost['cassandra'].from(now - 3.minutes).map(&:permalink).
255
+ should == %w(cequel1 cequel2 cequel3 cequel4)
256
+ end
257
+
187
258
  it 'should raise ArgumentError when called on partition key' do
188
259
  expect { Post.from('cassandra') }.
189
260
  to raise_error(Cequel::Record::IllegalQuery)
@@ -195,6 +266,16 @@ describe Cequel::Record::RecordSet do
195
266
  Post.at('cassandra').before('cequel3').map(&:title).
196
267
  should == (0...3).map { |i| "Cequel #{i}" }
197
268
  end
269
+
270
+ it 'should query Time range for Timeuuid key' do
271
+ PublishedPost['cassandra'].before(now - 1.minute).map(&:permalink).
272
+ should == %w(cequel0 cequel1 cequel2)
273
+ end
274
+
275
+ it 'should cast argument' do
276
+ Post.at('cassandra').before('cequel3'.force_encoding('ASCII-8BIT')).
277
+ map(&:title).should == (0...3).map { |i| "Cequel #{i}" }
278
+ end
198
279
  end
199
280
 
200
281
  describe '#upto' do
@@ -202,6 +283,16 @@ describe Cequel::Record::RecordSet do
202
283
  Post.at('cassandra').upto('cequel3').map(&:title).
203
284
  should == (0..3).map { |i| "Cequel #{i}" }
204
285
  end
286
+
287
+ it 'should cast argument' do
288
+ Post.at('cassandra').upto('cequel3'.force_encoding('ASCII-8BIT')).
289
+ map(&:title).should == (0..3).map { |i| "Cequel #{i}" }
290
+ end
291
+
292
+ it 'should query Time range for Timeuuid key' do
293
+ PublishedPost['cassandra'].upto(now - 1.minute).map(&:permalink).
294
+ should == %w(cequel0 cequel1 cequel2 cequel3)
295
+ end
205
296
  end
206
297
 
207
298
  describe '#in' do
@@ -210,10 +301,26 @@ describe Cequel::Record::RecordSet do
210
301
  should == (1..3).map { |i| "Cequel #{i}" }
211
302
  end
212
303
 
304
+ it 'should cast arguments' do
305
+ Post.at('cassandra').in('cequel1'.force_encoding('ASCII-8BIT')..
306
+ 'cequel3'.force_encoding('ASCII-8BIT')).
307
+ map(&:title).should == (1..3).map { |i| "Cequel #{i}" }
308
+ end
309
+
213
310
  it 'should return collection with exclusive upper bound' do
214
311
  Post.at('cassandra').in('cequel1'...'cequel3').map(&:title).
215
312
  should == (1...3).map { |i| "Cequel #{i}" }
216
313
  end
314
+
315
+ it 'should query Time range for Timeuuid key' do
316
+ PublishedPost['cassandra'].in((now - 3.minutes)..(now - 1.minute)).
317
+ map(&:permalink).should == %w(cequel1 cequel2 cequel3)
318
+ end
319
+
320
+ it 'should query Time range for Timeuuid key with exclusive upper bound' do
321
+ PublishedPost['cassandra'].in((now - 3.minutes)...(now - 1.minute)).
322
+ map(&:permalink).should == %w(cequel1 cequel2)
323
+ end
217
324
  end
218
325
 
219
326
  describe '#reverse' do
@@ -235,6 +342,11 @@ describe Cequel::Record::RecordSet do
235
342
  it 'should raise an error if range key is a partition key' do
236
343
  expect { Post.all.reverse }.to raise_error(Cequel::Record::IllegalQuery)
237
344
  end
345
+
346
+ it 'should use the correct ordering column in deeply nested models' do
347
+ Comment['cassandra']['cequel0'].reverse.map(&:body).
348
+ should == (0...5).map { |i| "Comment #{i}" }.reverse
349
+ end
238
350
  end
239
351
 
240
352
  describe 'last' do
@@ -295,6 +407,11 @@ describe Cequel::Record::RecordSet do
295
407
  should == %w(cequel0 cequel2 cequel4)
296
408
  end
297
409
 
410
+ it 'should cast argument for column' do
411
+ Post.where(:author_id, uuids.first.to_s).map(&:permalink).
412
+ should == %w(cequel0 cequel2 cequel4)
413
+ end
414
+
298
415
  it 'should raise ArgumentError if column is not recognized' do
299
416
  expect { Post.where(:bogus, 'Business') }.
300
417
  to raise_error(ArgumentError)
@@ -83,6 +83,10 @@ describe Cequel::Record::Schema do
83
83
  its(:clustering_columns) { should == [Cequel::Schema::Column.new(:id, :uuid)] }
84
84
  it { should be_compact_storage }
85
85
  its(:data_columns) { should == [Cequel::Schema::Column.new(:data, :text)] }
86
+
87
+ it 'should be able to synchronize schema again' do
88
+ expect { legacy_model.synchronize_schema }.to_not raise_error
89
+ end
86
90
  end
87
91
  end
88
92
  end
@@ -27,6 +27,20 @@ describe Cequel::Record::Set do
27
27
  end
28
28
  end
29
29
 
30
+ context 'updating' do
31
+ it 'should overwrite value' do
32
+ post.tags = Set['three', 'four']
33
+ post.save!
34
+ subject[:tags].should == Set['three', 'four']
35
+ end
36
+
37
+ it 'should cast collection before overwriting' do
38
+ post.tags = %w(three four)
39
+ post.save!
40
+ subject[:tags].should == Set['three', 'four']
41
+ end
42
+ end
43
+
30
44
  describe 'atomic modification' do
31
45
  before { scope.set_add(:tags, 'three') }
32
46
 
@@ -38,6 +52,11 @@ describe Cequel::Record::Set do
38
52
  post.tags.should == Set['one', 'two', 'four']
39
53
  end
40
54
 
55
+ it 'should cast before adding' do
56
+ post.tags.add(4)
57
+ post.tags.should == Set['one', 'two', '4']
58
+ end
59
+
41
60
  it 'should add without reading' do
42
61
  max_statements! 2
43
62
  unloaded_post.tags.add('four')
@@ -80,6 +99,11 @@ describe Cequel::Record::Set do
80
99
  post.tags.should == Set['one']
81
100
  end
82
101
 
102
+ it 'should cast before deleting' do
103
+ post.tags.delete(:two)
104
+ post.tags.should == Set['one']
105
+ end
106
+
83
107
  it 'should delete without reading' do
84
108
  max_statements! 2
85
109
  unloaded_post.tags.delete('two')
@@ -101,6 +125,11 @@ describe Cequel::Record::Set do
101
125
  post.tags.should == Set['a', 'b']
102
126
  end
103
127
 
128
+ it 'should cast before replacing' do
129
+ post.tags.replace(Set[1, 2, :three])
130
+ post.tags.should == Set['1', '2', 'three']
131
+ end
132
+
104
133
  it 'should replace without reading' do
105
134
  max_statements! 2
106
135
  unloaded_post.tags.replace(Set['a', 'b'])
@@ -381,9 +381,9 @@ describe Cequel::Schema::TableReader do
381
381
  its(:partition_key_columns) { should ==
382
382
  [Cequel::Schema::PartitionKey.new(:blog_subdomain, :text)] }
383
383
  its(:clustering_columns) { should ==
384
- [Cequel::Schema::ClusteringColumn.new(nil, :uuid)] }
384
+ [Cequel::Schema::ClusteringColumn.new(:column1, :uuid)] }
385
385
  its(:data_columns) { should ==
386
- [Cequel::Schema::DataColumn.new(nil, :text)] }
386
+ [Cequel::Schema::DataColumn.new(:value, :text)] }
387
387
  end
388
388
 
389
389
  end
@@ -76,6 +76,24 @@ module Cequel
76
76
  )
77
77
  end
78
78
 
79
+ def min_uuid(time = Time.now)
80
+ CassandraCQL::UUID.new(time, :randomize => false)
81
+ end
82
+
83
+ def max_uuid(time = Time.now)
84
+ time = time.stamp * 10 + SimpleUUID::UUID::GREGORIAN_EPOCH_OFFSET
85
+ # See http://github.com/spectra/ruby-uuid/
86
+ byte_array = [
87
+ time & 0xFFFF_FFFF,
88
+ time >> 32,
89
+ ((time >> 48) & 0x0FFF) | 0x1000,
90
+ (2**13 - 1) | SimpleUUID::UUID::VARIANT,
91
+ 2**16 - 1,
92
+ 2**32 - 1
93
+ ]
94
+ CassandraCQL::UUID.new(byte_array.pack("NnnnnN"))
95
+ end
96
+
79
97
  def cequel
80
98
  Helpers.cequel
81
99
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: cequel
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.0.pre.4
4
+ version: 1.0.0.pre.5
5
5
  platform: ruby
6
6
  authors:
7
7
  - Mat Brown
@@ -12,7 +12,7 @@ authors:
12
12
  autorequire:
13
13
  bindir: bin
14
14
  cert_chain: []
15
- date: 2013-09-30 00:00:00.000000000 Z
15
+ date: 2013-11-08 00:00:00.000000000 Z
16
16
  dependencies:
17
17
  - !ruby/object:Gem::Dependency
18
18
  name: activesupport
@@ -154,6 +154,7 @@ files:
154
154
  - lib/cequel/record/association_collection.rb
155
155
  - lib/cequel/record/associations.rb
156
156
  - lib/cequel/record/belongs_to_association.rb
157
+ - lib/cequel/record/bound.rb
157
158
  - lib/cequel/record/callbacks.rb
158
159
  - lib/cequel/record/collection.rb
159
160
  - lib/cequel/record/dirty.rb