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
@@ -1,81 +1,128 @@
|
|
1
|
+
require 'cequel/model'
|
1
2
|
require File.expand_path('../spec_helper', __FILE__)
|
2
3
|
|
3
4
|
describe Cequel::Model::Properties do
|
4
|
-
let(:post) { Post.new(:id => 1) }
|
5
5
|
|
6
|
-
|
7
|
-
|
6
|
+
describe 'property accessors' do
|
7
|
+
model :Post do
|
8
|
+
key :permalink, :text
|
9
|
+
column :title, :text
|
10
|
+
list :tags, :text
|
11
|
+
set :categories, :text
|
12
|
+
map :shares, :text, :int
|
13
|
+
|
14
|
+
def downcased_title=(downcased_title)
|
15
|
+
self.title = downcased_title.titleize
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
it 'should provide accessor for key' do
|
20
|
+
Post.new { |post| post.permalink = 'big-data' }.permalink.
|
21
|
+
should == 'big-data'
|
22
|
+
end
|
23
|
+
|
24
|
+
it 'should cast key to correct value' do
|
25
|
+
Post.new { |post| post.permalink = 44 }.permalink.
|
26
|
+
should == '44'
|
27
|
+
end
|
28
|
+
|
29
|
+
it 'should have nil key if unset' do
|
30
|
+
Post.new.permalink.should be_nil
|
31
|
+
end
|
32
|
+
|
33
|
+
it 'should provide accessor for data column' do
|
34
|
+
Post.new { |post| post.title = 'Big Data' }.title.should == 'Big Data'
|
35
|
+
end
|
36
|
+
|
37
|
+
it 'should cast data column to correct value' do
|
38
|
+
Post.new { |post| post.title = 'Big Data'.force_encoding('US-ASCII') }.
|
39
|
+
title.encoding.name.should == 'UTF-8'
|
40
|
+
end
|
41
|
+
|
42
|
+
it 'should have nil data column value if unset' do
|
43
|
+
Post.new.title.should be_nil
|
44
|
+
end
|
45
|
+
|
46
|
+
it 'should allow setting attributes via #attributes=' do
|
47
|
+
Post.new.tap { |post| post.attributes = {:title => 'Big Data' }}.
|
48
|
+
title.should == 'Big Data'
|
49
|
+
end
|
50
|
+
|
51
|
+
it 'should use writers when setting attributes' do
|
52
|
+
Post.new.tap { |post| post.attributes = {:downcased_title => 'big data' }}.
|
53
|
+
title.should == 'Big Data'
|
54
|
+
end
|
55
|
+
|
56
|
+
it 'should take attribute arguments to ::new' do
|
57
|
+
Post.new(:downcased_title => 'big data').title.should == 'Big Data'
|
58
|
+
end
|
59
|
+
|
60
|
+
it 'should provide accessor for list column' do
|
61
|
+
Post.new { |post| post.tags = %w(one two three) }.tags.
|
62
|
+
should == %w(one two three)
|
63
|
+
end
|
64
|
+
|
65
|
+
it 'should cast values in list column' do
|
66
|
+
Post.new { |post| post.tags = Set[1, 2, 3] }.tags.
|
67
|
+
should == %w(1 2 3)
|
68
|
+
end
|
69
|
+
|
70
|
+
it 'should have empty list column value if unset' do
|
71
|
+
Post.new.tags.should == []
|
72
|
+
end
|
73
|
+
|
74
|
+
it 'should provide accessor for set column' do
|
75
|
+
Post.new { |post| post.categories = Set['Big Data', 'Cassandra'] }.
|
76
|
+
categories.should == Set['Big Data', 'Cassandra']
|
77
|
+
end
|
78
|
+
|
79
|
+
it 'should cast values to correct type' do
|
80
|
+
Post.new { |post| post.categories = [1, 2, 3] }.categories.
|
81
|
+
should == Set['1', '2', '3']
|
82
|
+
end
|
83
|
+
|
84
|
+
it 'should have empty set column value if present' do
|
85
|
+
Post.new.categories.should == Set[]
|
86
|
+
end
|
87
|
+
|
88
|
+
it 'should provide accessor for map column' do
|
89
|
+
Post.new { |post| post.shares = {'facebook' => 1, 'twitter' => 2}}.
|
90
|
+
shares.should == {'facebook' => 1, 'twitter' => 2}
|
91
|
+
end
|
92
|
+
|
93
|
+
it 'should cast values for map column' do
|
94
|
+
Post.new { |post| post.shares = [[:facebook, '1'], [:twitter, '2']] }.
|
95
|
+
shares.should == {'facebook' => 1, 'twitter' => 2}
|
96
|
+
end
|
97
|
+
|
98
|
+
it 'should set map column to empty hash by default' do
|
99
|
+
Post.new.shares.should == {}
|
100
|
+
end
|
101
|
+
end
|
102
|
+
|
103
|
+
describe 'configured property defaults' do
|
104
|
+
model :Post do
|
105
|
+
key :permalink, :text
|
106
|
+
column :title, :text, :default => 'New Post'
|
107
|
+
list :tags, :text, :default => ['new']
|
108
|
+
set :categories, :text, :default => Set['Big Data']
|
109
|
+
map :shares, :text, :int, :default => {'facebook' => 0}
|
110
|
+
end
|
111
|
+
|
112
|
+
it 'should respect default for data column' do
|
113
|
+
Post.new.title.should == 'New Post'
|
114
|
+
end
|
115
|
+
|
116
|
+
it 'should respect default for list column' do
|
117
|
+
Post.new.tags.should == ['new']
|
118
|
+
end
|
119
|
+
|
120
|
+
it 'should respect default for set column' do
|
121
|
+
Post.new.categories.should == Set['Big Data']
|
122
|
+
end
|
123
|
+
|
124
|
+
it 'should respect default for map column' do
|
125
|
+
Post.new.shares.should == {'facebook' => 0}
|
126
|
+
end
|
8
127
|
end
|
9
|
-
|
10
|
-
it 'should return key alias from class' do
|
11
|
-
Post.key_alias.should == :id
|
12
|
-
end
|
13
|
-
|
14
|
-
it 'should return key for to_key' do
|
15
|
-
post.to_key.should == [1]
|
16
|
-
end
|
17
|
-
|
18
|
-
it 'should return param for to_param' do
|
19
|
-
post.persisted!
|
20
|
-
post.to_param.should == '1'
|
21
|
-
end
|
22
|
-
|
23
|
-
it 'should have getter and setter for column' do
|
24
|
-
post.title = 'Object/row mapping'
|
25
|
-
post.title.should == 'Object/row mapping'
|
26
|
-
end
|
27
|
-
|
28
|
-
it 'should have ? accessor for boolean column' do
|
29
|
-
post.published = true
|
30
|
-
post.published?.should be_true
|
31
|
-
end
|
32
|
-
|
33
|
-
it 'should not have ? accessor for non-boolean column' do
|
34
|
-
expect { post.title? }.to raise_error(NoMethodError)
|
35
|
-
end
|
36
|
-
|
37
|
-
it 'should expose column names on class' do
|
38
|
-
Post.column_names[0..1].should == [:id, :title]
|
39
|
-
end
|
40
|
-
|
41
|
-
it 'should expose column objects on class' do
|
42
|
-
Post.columns[0..1].map { |col| [col.name, col.type] }.
|
43
|
-
should == [[:id, :int], [:title, :varchar]]
|
44
|
-
end
|
45
|
-
|
46
|
-
it 'should expose #attributes' do
|
47
|
-
post.title = 'Cequel'
|
48
|
-
post.attributes.
|
49
|
-
should == {:id => 1, :title => 'Cequel'}.with_indifferent_access
|
50
|
-
end
|
51
|
-
|
52
|
-
it 'should not return nil values with attributes' do
|
53
|
-
post.title = nil
|
54
|
-
post.attributes.should == {:id => 1}.with_indifferent_access
|
55
|
-
end
|
56
|
-
|
57
|
-
it 'should set attributes' do
|
58
|
-
post.attributes = { :title => 'Cequel' }
|
59
|
-
post.id.should == 1
|
60
|
-
post.title.should == 'Cequel'
|
61
|
-
end
|
62
|
-
|
63
|
-
it 'should set attributes from constructor' do
|
64
|
-
Post.new(:id => 1, :title => 'Cequel').title.should == 'Cequel'
|
65
|
-
end
|
66
|
-
|
67
|
-
it 'should set default column values for new instances' do
|
68
|
-
Blog.new.published.should == true
|
69
|
-
end
|
70
|
-
|
71
|
-
it 'should use key to compare equality' do
|
72
|
-
Post.new(:id => 1).should == Post.new(:id => 1)
|
73
|
-
Post.new(:id => 1).should_not == Post.new(:id => 2)
|
74
|
-
Post.new(:id => 1).should_not == Blog.new(:id => 1)
|
75
|
-
end
|
76
|
-
|
77
|
-
it 'should use #generate_key method when implemented' do
|
78
|
-
Comment.new.id.should be_a(SimpleUUID::UUID)
|
79
|
-
end
|
80
|
-
|
81
128
|
end
|
@@ -0,0 +1,285 @@
|
|
1
|
+
require File.expand_path('../spec_helper', __FILE__)
|
2
|
+
|
3
|
+
describe Cequel::Model::RecordSet do
|
4
|
+
model :Blog do
|
5
|
+
key :subdomain, :text
|
6
|
+
column :name, :text
|
7
|
+
column :description, :text
|
8
|
+
end
|
9
|
+
|
10
|
+
model :Post do
|
11
|
+
key :blog_subdomain, :text
|
12
|
+
key :permalink, :text
|
13
|
+
column :title, :text
|
14
|
+
column :body, :text
|
15
|
+
column :author_id, :uuid
|
16
|
+
list :tags, :text
|
17
|
+
set :categories, :text
|
18
|
+
map :shares, :text, :int
|
19
|
+
end
|
20
|
+
|
21
|
+
let(:subdomains) { [] }
|
22
|
+
|
23
|
+
before do
|
24
|
+
cequel.batch do
|
25
|
+
3.times do |i|
|
26
|
+
Blog.new do |blog|
|
27
|
+
subdomains << blog.subdomain = "blog-#{i}"
|
28
|
+
blog.name = "Blog #{i}"
|
29
|
+
blog.description = "This is Blog number #{i}"
|
30
|
+
end.save
|
31
|
+
end
|
32
|
+
end
|
33
|
+
cequel.batch do
|
34
|
+
5.times do |i|
|
35
|
+
cequel[:posts].insert(
|
36
|
+
:blog_subdomain => 'cassandra',
|
37
|
+
:permalink => "cequel#{i}",
|
38
|
+
:title => "Cequel #{i}",
|
39
|
+
:body => "Post number #{i}"
|
40
|
+
)
|
41
|
+
cequel[:posts].insert(
|
42
|
+
:blog_subdomain => 'postgres',
|
43
|
+
:permalink => "sequel#{i}",
|
44
|
+
:title => "Sequel #{i}"
|
45
|
+
)
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
describe '::find' do
|
51
|
+
context 'simple primary key' do
|
52
|
+
subject { Blog.find('blog-0') }
|
53
|
+
|
54
|
+
its(:subdomain) { should == 'blog-0' }
|
55
|
+
its(:name) { should == 'Blog 0' }
|
56
|
+
|
57
|
+
it { should be_persisted }
|
58
|
+
it { should_not be_transient }
|
59
|
+
specify { Blog.new.should_not be_persisted }
|
60
|
+
specify { Blog.new.should be_transient }
|
61
|
+
|
62
|
+
specify do
|
63
|
+
expect { Blog.find('bogus') }.
|
64
|
+
to raise_error(Cequel::Model::RecordNotFound)
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
context 'compound primary key' do
|
69
|
+
subject { Post['cassandra'].find('cequel0') }
|
70
|
+
|
71
|
+
its(:blog_subdomain) { should == 'cassandra' }
|
72
|
+
its(:permalink) { should == 'cequel0' }
|
73
|
+
its(:title) { should == 'Cequel 0' }
|
74
|
+
|
75
|
+
it { should be_persisted }
|
76
|
+
it { should_not be_transient }
|
77
|
+
specify { Post.new.should_not be_persisted }
|
78
|
+
specify { Post.new.should be_transient }
|
79
|
+
|
80
|
+
specify do
|
81
|
+
expect { Post['cequel'].find('bogus')}.
|
82
|
+
to raise_error(Cequel::Model::RecordNotFound)
|
83
|
+
end
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
describe '::[]' do
|
88
|
+
context 'simple primary key' do
|
89
|
+
subject { Blog['blog-0'] }
|
90
|
+
|
91
|
+
it 'should not query the database' do
|
92
|
+
disallow_queries!
|
93
|
+
subject.subdomain.should == 'blog-0'
|
94
|
+
end
|
95
|
+
|
96
|
+
it 'should lazily query the database when attribute accessed' do
|
97
|
+
subject.name.should == 'Blog 0'
|
98
|
+
end
|
99
|
+
|
100
|
+
it 'should get all eager-loadable attributes on first lazy load' do
|
101
|
+
subject.name
|
102
|
+
disallow_queries!
|
103
|
+
subject.description.should == 'This is Blog number 0'
|
104
|
+
end
|
105
|
+
end
|
106
|
+
|
107
|
+
context 'compound primary key' do
|
108
|
+
subject { Post['cassandra']['cequel0'] }
|
109
|
+
|
110
|
+
it 'should not query the database' do
|
111
|
+
expect(cequel).not_to receive(:execute)
|
112
|
+
subject.blog_subdomain.should == 'cassandra'
|
113
|
+
subject.permalink.should == 'cequel0'
|
114
|
+
end
|
115
|
+
|
116
|
+
it 'should lazily query the database when attribute accessed' do
|
117
|
+
subject.title.should == 'Cequel 0'
|
118
|
+
end
|
119
|
+
|
120
|
+
it 'should get all eager-loadable attributes on first lazy load' do
|
121
|
+
subject.title
|
122
|
+
expect(cequel).not_to receive(:execute)
|
123
|
+
subject.body.should == 'Post number 0'
|
124
|
+
end
|
125
|
+
end
|
126
|
+
end
|
127
|
+
|
128
|
+
describe '#all' do
|
129
|
+
it 'should return all the records' do
|
130
|
+
Blog.all.map(&:subdomain).should =~ subdomains
|
131
|
+
end
|
132
|
+
end
|
133
|
+
|
134
|
+
describe '#find_each' do
|
135
|
+
it 'should respect :batch_size argument' do
|
136
|
+
cequel.should_receive(:execute).twice.and_call_original
|
137
|
+
Blog.find_each(:batch_size => 2).map(&:subdomain).
|
138
|
+
should =~ subdomains
|
139
|
+
end
|
140
|
+
it 'should iterate over all keys' do
|
141
|
+
Post.find_each(:batch_size => 2).map(&:title).
|
142
|
+
should =~ (0...5).flat_map { |i| ["Cequel #{i}", "Sequel #{i}"] }
|
143
|
+
end
|
144
|
+
end
|
145
|
+
|
146
|
+
describe '#at' do
|
147
|
+
it 'should return partial collection' do
|
148
|
+
Post.at('cassandra').find_each(:batch_size => 2).map(&:title).
|
149
|
+
should == (0...5).map { |i| "Cequel #{i}" }
|
150
|
+
end
|
151
|
+
end
|
152
|
+
|
153
|
+
describe '#[]' do
|
154
|
+
it 'should create partial collection if not all keys specified' do
|
155
|
+
Post['cassandra'].find_each(:batch_size => 2).map(&:title).
|
156
|
+
should == (0...5).map { |i| "Cequel #{i}" }
|
157
|
+
end
|
158
|
+
end
|
159
|
+
|
160
|
+
describe '#/' do
|
161
|
+
it 'should behave like #at' do
|
162
|
+
(Post / 'cassandra').find_each(:batch_size => 2).map(&:title).
|
163
|
+
should == (0...5).map { |i| "Cequel #{i}" }
|
164
|
+
end
|
165
|
+
end
|
166
|
+
|
167
|
+
describe '#after' do
|
168
|
+
it 'should return collection after given key' do
|
169
|
+
Post.at('cassandra').after('cequel1').map(&:title).
|
170
|
+
should == (2...5).map { |i| "Cequel #{i}" }
|
171
|
+
end
|
172
|
+
end
|
173
|
+
|
174
|
+
describe '#from' do
|
175
|
+
it 'should return collection starting with given key' do
|
176
|
+
Post.at('cassandra').from('cequel1').map(&:title).
|
177
|
+
should == (1...5).map { |i| "Cequel #{i}" }
|
178
|
+
end
|
179
|
+
|
180
|
+
it 'should raise ArgumentError when called on partition key' do
|
181
|
+
expect { Post.from('cassandra') }.to raise_error(NoMethodError)
|
182
|
+
end
|
183
|
+
end
|
184
|
+
|
185
|
+
describe '#before' do
|
186
|
+
it 'should return collection before given key' do
|
187
|
+
Post.at('cassandra').before('cequel3').map(&:title).
|
188
|
+
should == (0...3).map { |i| "Cequel #{i}" }
|
189
|
+
end
|
190
|
+
end
|
191
|
+
|
192
|
+
describe '#upto' do
|
193
|
+
it 'should return collection up to given key' do
|
194
|
+
Post.at('cassandra').upto('cequel3').map(&:title).
|
195
|
+
should == (0..3).map { |i| "Cequel #{i}" }
|
196
|
+
end
|
197
|
+
end
|
198
|
+
|
199
|
+
describe '#in' do
|
200
|
+
it 'should return collection with inclusive upper bound' do
|
201
|
+
Post.at('cassandra').in('cequel1'..'cequel3').map(&:title).
|
202
|
+
should == (1..3).map { |i| "Cequel #{i}" }
|
203
|
+
end
|
204
|
+
|
205
|
+
it 'should return collection with exclusive upper bound' do
|
206
|
+
Post.at('cassandra').in('cequel1'...'cequel3').map(&:title).
|
207
|
+
should == (1...3).map { |i| "Cequel #{i}" }
|
208
|
+
end
|
209
|
+
end
|
210
|
+
|
211
|
+
describe '#reverse' do
|
212
|
+
it 'should not call the database' do
|
213
|
+
disallow_queries!
|
214
|
+
Post.at('cassandra').reverse
|
215
|
+
end
|
216
|
+
|
217
|
+
it 'should return collection in reverse' do
|
218
|
+
Post.at('cassandra').reverse.map(&:title).
|
219
|
+
should == (0...5).map { |i| "Cequel #{i}" }.reverse
|
220
|
+
end
|
221
|
+
|
222
|
+
it 'should batch iterate over collection in reverse' do
|
223
|
+
Post.at('cassandra').reverse.find_each(:batch_size => 2).map(&:title).
|
224
|
+
should == (0...5).map { |i| "Cequel #{i}" }.reverse
|
225
|
+
end
|
226
|
+
|
227
|
+
it 'should raise an error if range key is a partition key' do
|
228
|
+
expect { Post.all.reverse }.to raise_error(NoMethodError)
|
229
|
+
end
|
230
|
+
end
|
231
|
+
|
232
|
+
describe 'last' do
|
233
|
+
it 'should return the last instance' do
|
234
|
+
Post.at('cassandra').last.title.should == "Cequel 4"
|
235
|
+
end
|
236
|
+
end
|
237
|
+
|
238
|
+
describe '#first' do
|
239
|
+
context 'with no arguments' do
|
240
|
+
it 'should return an arbitrary record' do
|
241
|
+
subdomains.should include(Blog.first.subdomain)
|
242
|
+
end
|
243
|
+
end
|
244
|
+
|
245
|
+
context 'with a given size' do
|
246
|
+
subject { Blog.first(2) }
|
247
|
+
|
248
|
+
it { should be_a(Array) }
|
249
|
+
it { should have(2).items }
|
250
|
+
specify { (subject.map(&:subdomain) & subdomains).should have(2).items }
|
251
|
+
end
|
252
|
+
end
|
253
|
+
|
254
|
+
describe '#limit' do
|
255
|
+
it 'should return the number of blogs requested' do
|
256
|
+
Blog.limit(2).should have(2).entries
|
257
|
+
end
|
258
|
+
end
|
259
|
+
|
260
|
+
describe '#select' do
|
261
|
+
context 'with no block' do
|
262
|
+
subject { Blog.select(:subdomain, :name).first }
|
263
|
+
|
264
|
+
it { should be_loaded(:name) }
|
265
|
+
it { should_not be_loaded(:description) }
|
266
|
+
specify { expect { subject.name }.to_not raise_error }
|
267
|
+
specify { expect { subject.description }.
|
268
|
+
to raise_error(Cequel::Model::MissingAttributeError) }
|
269
|
+
end
|
270
|
+
|
271
|
+
context 'with block' do
|
272
|
+
it 'should delegate to the Enumerable method' do
|
273
|
+
Blog.all.select { |p| p.subdomain[/\d+/].to_i.even? }.
|
274
|
+
map(&:subdomain).should =~ %w(blog-0 blog-2)
|
275
|
+
end
|
276
|
+
end
|
277
|
+
end
|
278
|
+
|
279
|
+
describe '#count' do
|
280
|
+
it 'should count records' do
|
281
|
+
Blog.count.should == 3
|
282
|
+
end
|
283
|
+
end
|
284
|
+
|
285
|
+
end
|