dynamoid 0.6.1 → 0.7.0
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.
- data/.travis.yml +4 -0
- data/Gemfile +3 -2
- data/Gemfile.lock +40 -45
- data/README.markdown +55 -25
- data/Rakefile +31 -0
- data/VERSION +1 -1
- data/doc/Dynamoid.html +58 -42
- data/doc/Dynamoid/Adapter.html +666 -179
- data/doc/Dynamoid/Adapter/AwsSdk.html +752 -236
- data/doc/Dynamoid/Associations.html +28 -21
- data/doc/Dynamoid/Associations/Association.html +102 -49
- data/doc/Dynamoid/Associations/BelongsTo.html +28 -25
- data/doc/Dynamoid/Associations/ClassMethods.html +95 -52
- data/doc/Dynamoid/Associations/HasAndBelongsToMany.html +28 -25
- data/doc/Dynamoid/Associations/HasMany.html +28 -25
- data/doc/Dynamoid/Associations/HasOne.html +28 -25
- data/doc/Dynamoid/Associations/ManyAssociation.html +138 -94
- data/doc/Dynamoid/Associations/SingleAssociation.html +67 -38
- data/doc/Dynamoid/Components.html +60 -22
- data/doc/Dynamoid/Config.html +61 -44
- data/doc/Dynamoid/Config/Options.html +90 -61
- data/doc/Dynamoid/Criteria.html +28 -21
- data/doc/Dynamoid/Criteria/Chain.html +508 -100
- data/doc/Dynamoid/Criteria/ClassMethods.html +26 -19
- data/doc/Dynamoid/Dirty.html +424 -0
- data/doc/Dynamoid/Dirty/ClassMethods.html +174 -0
- data/doc/Dynamoid/Document.html +451 -84
- data/doc/Dynamoid/Document/ClassMethods.html +281 -102
- data/doc/Dynamoid/Errors.html +29 -22
- data/doc/Dynamoid/Errors/ConditionalCheckFailedException.html +141 -0
- data/doc/Dynamoid/Errors/DocumentNotValid.html +36 -25
- data/doc/Dynamoid/Errors/Error.html +27 -20
- data/doc/Dynamoid/Errors/InvalidField.html +27 -19
- data/doc/Dynamoid/Errors/InvalidQuery.html +131 -0
- data/doc/Dynamoid/Errors/MissingRangeKey.html +27 -19
- data/doc/Dynamoid/Fields.html +94 -77
- data/doc/Dynamoid/Fields/ClassMethods.html +166 -37
- data/doc/Dynamoid/Finders.html +28 -21
- data/doc/Dynamoid/Finders/ClassMethods.html +505 -78
- data/doc/Dynamoid/IdentityMap.html +492 -0
- data/doc/Dynamoid/IdentityMap/ClassMethods.html +534 -0
- data/doc/Dynamoid/Indexes.html +41 -28
- data/doc/Dynamoid/Indexes/ClassMethods.html +45 -29
- data/doc/Dynamoid/Indexes/Index.html +100 -62
- data/doc/Dynamoid/Middleware.html +115 -0
- data/doc/Dynamoid/Middleware/IdentityMap.html +264 -0
- data/doc/Dynamoid/Persistence.html +326 -85
- data/doc/Dynamoid/Persistence/ClassMethods.html +275 -109
- data/doc/Dynamoid/Validations.html +47 -31
- data/doc/_index.html +116 -71
- data/doc/class_list.html +13 -7
- data/doc/css/full_list.css +4 -2
- data/doc/css/style.css +60 -44
- data/doc/file.LICENSE.html +26 -19
- data/doc/file.README.html +152 -48
- data/doc/file_list.html +14 -8
- data/doc/frames.html +20 -5
- data/doc/index.html +152 -48
- data/doc/js/app.js +52 -43
- data/doc/js/full_list.js +14 -9
- data/doc/js/jquery.js +4 -16
- data/doc/method_list.html +446 -540
- data/doc/top-level-namespace.html +27 -20
- data/{Dynamoid.gemspec → dynamoid.gemspec} +21 -8
- data/lib/dynamoid/adapter.rb +11 -10
- data/lib/dynamoid/adapter/aws_sdk.rb +40 -19
- data/lib/dynamoid/components.rb +2 -1
- data/lib/dynamoid/criteria/chain.rb +29 -11
- data/lib/dynamoid/dirty.rb +6 -0
- data/lib/dynamoid/document.rb +34 -19
- data/lib/dynamoid/fields.rb +36 -30
- data/lib/dynamoid/finders.rb +7 -5
- data/lib/dynamoid/persistence.rb +37 -10
- data/spec/app/models/address.rb +2 -0
- data/spec/app/models/camel_case.rb +10 -0
- data/spec/app/models/car.rb +6 -0
- data/spec/app/models/nuclear_submarine.rb +5 -0
- data/spec/app/models/subscription.rb +2 -2
- data/spec/app/models/vehicle.rb +7 -0
- data/spec/dynamoid/adapter/aws_sdk_spec.rb +20 -11
- data/spec/dynamoid/adapter_spec.rb +67 -82
- data/spec/dynamoid/associations/association_spec.rb +30 -30
- data/spec/dynamoid/criteria/chain_spec.rb +56 -9
- data/spec/dynamoid/criteria_spec.rb +3 -0
- data/spec/dynamoid/dirty_spec.rb +8 -0
- data/spec/dynamoid/document_spec.rb +109 -47
- data/spec/dynamoid/fields_spec.rb +32 -3
- data/spec/dynamoid/finders_spec.rb +12 -0
- data/spec/dynamoid/persistence_spec.rb +73 -8
- data/spec/spec_helper.rb +1 -0
- data/spec/support/with_partitioning.rb +15 -0
- metadata +22 -9
|
@@ -1,17 +1,21 @@
|
|
|
1
1
|
require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
|
|
2
2
|
|
|
3
|
-
describe
|
|
3
|
+
describe Dynamoid::Adapter do
|
|
4
4
|
|
|
5
|
+
def test_table; 'dynamoid_tests_TestTable'; end
|
|
6
|
+
let(:single_id){'123'}
|
|
7
|
+
let(:many_ids){%w(1 2)}
|
|
8
|
+
|
|
5
9
|
before(:all) do
|
|
6
|
-
|
|
10
|
+
described_class.create_table(test_table, :id) unless described_class.list_tables.include?(test_table)
|
|
7
11
|
end
|
|
8
12
|
|
|
9
13
|
it 'extends itself automatically' do
|
|
10
|
-
lambda {
|
|
14
|
+
lambda {described_class.list_tables}.should_not raise_error
|
|
11
15
|
end
|
|
12
|
-
|
|
13
|
-
it 'raises
|
|
14
|
-
lambda {
|
|
16
|
+
|
|
17
|
+
it 'raises NoMethodError if we try a method that is not on the child' do
|
|
18
|
+
lambda {described_class.foobar}.should raise_error(NoMethodError)
|
|
15
19
|
end
|
|
16
20
|
|
|
17
21
|
context 'without partioning' do
|
|
@@ -25,145 +29,126 @@ describe "Dynamoid::Adapter" do
|
|
|
25
29
|
end
|
|
26
30
|
|
|
27
31
|
it 'writes through the adapter' do
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
Dynamoid::Adapter.write('dynamoid_tests_TestTable', {:id => '123'})
|
|
32
|
+
described_class.expects(:put_item).with(test_table, {:id => single_id}, nil).returns(true)
|
|
33
|
+
described_class.write(test_table, {:id => single_id})
|
|
31
34
|
end
|
|
32
35
|
|
|
33
36
|
it 'reads through the adapter for one ID' do
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
Dynamoid::Adapter.read('dynamoid_tests_TestTable', '123')
|
|
37
|
+
described_class.expects(:get_item).with(test_table, single_id, {}).returns(true)
|
|
38
|
+
described_class.read(test_table, single_id)
|
|
37
39
|
end
|
|
38
40
|
|
|
39
41
|
it 'reads through the adapter for many IDs' do
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
Dynamoid::Adapter.read('dynamoid_tests_TestTable', ['1', '2'])
|
|
42
|
+
described_class.expects(:batch_get_item).with({test_table => many_ids}, {}).returns(true)
|
|
43
|
+
described_class.read(test_table, many_ids)
|
|
43
44
|
end
|
|
44
|
-
|
|
45
|
-
it 'delete through the adapter for one ID' do
|
|
46
|
-
Dynamoid::Adapter.expects(:delete_item).with('dynamoid_tests_TestTable', '123', {}).returns(nil)
|
|
47
45
|
|
|
48
|
-
|
|
46
|
+
it 'delete through the adapter for one ID' do
|
|
47
|
+
described_class.expects(:delete_item).with(test_table, single_id, {}).returns(nil)
|
|
48
|
+
described_class.delete(test_table, single_id)
|
|
49
49
|
end
|
|
50
|
-
|
|
51
|
-
it 'deletes through the adapter for many IDs' do
|
|
52
|
-
Dynamoid::Adapter.expects(:batch_delete_item).with({'dynamoid_tests_TestTable' => ['1', '2']}).returns(nil)
|
|
53
50
|
|
|
54
|
-
|
|
51
|
+
it 'deletes through the adapter for many IDs' do
|
|
52
|
+
described_class.expects(:batch_delete_item).with({test_table => many_ids}).returns(nil)
|
|
53
|
+
described_class.delete(test_table, many_ids)
|
|
55
54
|
end
|
|
56
|
-
|
|
57
|
-
it 'reads through the adapter for one ID and a range key' do
|
|
58
|
-
Dynamoid::Adapter.expects(:get_item).with('dynamoid_tests_TestTable', '123', :range_key => 2.0).returns(true)
|
|
59
55
|
|
|
60
|
-
|
|
56
|
+
it 'reads through the adapter for one ID and a range key' do
|
|
57
|
+
described_class.expects(:get_item).with(test_table, single_id, :range_key => 2.0).returns(true)
|
|
58
|
+
described_class.read(test_table, single_id, :range_key => 2.0)
|
|
61
59
|
end
|
|
62
|
-
|
|
63
|
-
it 'reads through the adapter for many IDs and a range key' do
|
|
64
|
-
Dynamoid::Adapter.expects(:batch_get_item).with({'dynamoid_tests_TestTable' => [['1', 2.0], ['2', 2.0]]}).returns(true)
|
|
65
60
|
|
|
66
|
-
|
|
61
|
+
it 'reads through the adapter for many IDs and a range key' do
|
|
62
|
+
described_class.expects(:batch_get_item).with({test_table => [['1', 2.0], ['2', 2.0]]}, {}).returns(true)
|
|
63
|
+
described_class.read(test_table, many_ids, :range_key => 2.0)
|
|
67
64
|
end
|
|
68
|
-
|
|
69
|
-
it 'deletes through the adapter for one ID and a range key' do
|
|
70
|
-
Dynamoid::Adapter.expects(:delete_item).with('dynamoid_tests_TestTable', '123', :range_key => 2.0).returns(nil)
|
|
71
65
|
|
|
72
|
-
|
|
66
|
+
it 'deletes through the adapter for one ID and a range key' do
|
|
67
|
+
described_class.expects(:delete_item).with(test_table, single_id, :range_key => 2.0).returns(nil)
|
|
68
|
+
described_class.delete(test_table, single_id, :range_key => 2.0)
|
|
73
69
|
end
|
|
74
|
-
|
|
75
|
-
it 'deletes through the adapter for many IDs and a range key' do
|
|
76
|
-
Dynamoid::Adapter.expects(:batch_delete_item).with({'dynamoid_tests_TestTable' => [['1', 2.0], ['2', 2.0]]}).returns(nil)
|
|
77
70
|
|
|
78
|
-
|
|
71
|
+
it 'deletes through the adapter for many IDs and a range key' do
|
|
72
|
+
described_class.expects(:batch_delete_item).with({test_table => [['1', 2.0], ['2', 2.0]]}).returns(nil)
|
|
73
|
+
described_class.delete(test_table, many_ids, :range_key => [2.0,2.0])
|
|
79
74
|
end
|
|
80
75
|
end
|
|
81
76
|
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
Dynamoid::Config.partitioning = true
|
|
86
|
-
end
|
|
87
|
-
|
|
88
|
-
after(:all) do
|
|
89
|
-
Dynamoid::Config.partitioning = @previous_value
|
|
90
|
-
end
|
|
91
|
-
|
|
77
|
+
configured_with 'partitioning' do
|
|
78
|
+
let(:partition_range){0...Dynamoid::Config.partition_size}
|
|
79
|
+
|
|
92
80
|
it 'writes through the adapter' do
|
|
93
81
|
Random.expects(:rand).with(Dynamoid::Config.partition_size).once.returns(0)
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
82
|
+
described_class.write(test_table, {:id => 'testid'})
|
|
83
|
+
|
|
84
|
+
described_class.get_item(test_table, 'testid.0')[:id].should == 'testid.0'
|
|
85
|
+
described_class.get_item(test_table, 'testid.0')[:updated_at].should_not be_nil
|
|
98
86
|
end
|
|
99
87
|
|
|
100
88
|
it 'reads through the adapter for one ID' do
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
Dynamoid::Adapter.read('dynamoid_tests_TestTable', '123')
|
|
89
|
+
described_class.expects(:batch_get_item).with({test_table => partition_range.map{|n| "123.#{n}"}}, {}).returns({})
|
|
90
|
+
described_class.read(test_table, single_id)
|
|
104
91
|
end
|
|
105
92
|
|
|
106
93
|
it 'reads through the adapter for many IDs' do
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
Dynamoid::Adapter.read('dynamoid_tests_TestTable', ['1', '2'])
|
|
94
|
+
described_class.expects(:batch_get_item).with({test_table => partition_range.map{|n| "1.#{n}"} + partition_range.map{|n| "2.#{n}"}}, {}).returns({})
|
|
95
|
+
described_class.read(test_table, many_ids)
|
|
110
96
|
end
|
|
111
97
|
|
|
112
98
|
it 'reads through the adapter for one ID and a range key' do
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
Dynamoid::Adapter.read('dynamoid_tests_TestTable', '123', :range_key => 2.0)
|
|
99
|
+
described_class.expects(:batch_get_item).with({test_table => partition_range.map{|n| ["123.#{n}", 2.0]}}, {}).returns({})
|
|
100
|
+
described_class.read(test_table, single_id, :range_key => 2.0)
|
|
116
101
|
end
|
|
117
102
|
|
|
118
103
|
it 'reads through the adapter for many IDs and a range key' do
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
Dynamoid::Adapter.read('dynamoid_tests_TestTable', ['1', '2'], :range_key => 2.0)
|
|
104
|
+
described_class.expects(:batch_get_item).with({test_table => partition_range.map{|n| ["1.#{n}", 2.0]} + partition_range.map{|n| ["2.#{n}", 2.0]}}, {}).returns({})
|
|
105
|
+
described_class.read(test_table, many_ids, :range_key => 2.0)
|
|
122
106
|
end
|
|
123
107
|
|
|
124
108
|
it 'returns an ID with all partitions' do
|
|
125
|
-
|
|
109
|
+
described_class.id_with_partitions('1').should =~ partition_range.map{|n| "1.#{n}"}
|
|
126
110
|
end
|
|
127
111
|
|
|
128
112
|
it 'returns an ID and range key with all partitions' do
|
|
129
|
-
|
|
113
|
+
described_class.id_with_partitions([['1', 1.0]]).should =~ partition_range.map{|n| ["1.#{n}", 1.0]}
|
|
130
114
|
end
|
|
131
115
|
|
|
132
116
|
it 'returns a result for one partitioned element' do
|
|
133
117
|
@time = DateTime.now
|
|
134
|
-
@array =[{:id => '1.0', :updated_at => @time - 6.hours},
|
|
118
|
+
@array =[{:id => '1.0', :updated_at => @time - 6.hours},
|
|
119
|
+
{:id => '1.1', :updated_at => @time - 3.hours},
|
|
120
|
+
{:id => '1.2', :updated_at => @time - 1.hour},
|
|
121
|
+
{:id => '1.3', :updated_at => @time - 6.hours},
|
|
122
|
+
{:id => '2.0', :updated_at => @time}]
|
|
135
123
|
|
|
136
|
-
|
|
124
|
+
described_class.result_for_partition(@array,test_table).should =~ [{:id => '1', :updated_at => @time - 1.hour},
|
|
125
|
+
{:id => '2', :updated_at => @time}]
|
|
137
126
|
end
|
|
138
127
|
|
|
139
128
|
it 'returns a valid original id and partition number' do
|
|
140
129
|
@id = "12345.387327.-sdf3"
|
|
141
130
|
@partition_number = "4"
|
|
142
|
-
|
|
131
|
+
described_class.get_original_id_and_partition("#{@id}.#{@partition_number}").should == [@id, @partition_number]
|
|
143
132
|
end
|
|
144
133
|
|
|
145
134
|
it 'delete through the adapter for one ID' do
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
Dynamoid::Adapter.delete('dynamoid_tests_TestTable', '123')
|
|
135
|
+
described_class.expects(:batch_delete_item).with(test_table => partition_range.map{|n| "123.#{n}"}).returns(nil)
|
|
136
|
+
described_class.delete(test_table, single_id)
|
|
149
137
|
end
|
|
150
138
|
|
|
151
139
|
it 'deletes through the adapter for many IDs' do
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
Dynamoid::Adapter.delete('dynamoid_tests_TestTable', ['1', '2'])
|
|
140
|
+
described_class.expects(:batch_delete_item).with(test_table => partition_range.map{|n| "1.#{n}"} + partition_range.map{|n| "2.#{n}"}).returns(nil)
|
|
141
|
+
described_class.delete(test_table, many_ids)
|
|
155
142
|
end
|
|
156
143
|
|
|
157
144
|
it 'deletes through the adapter for one ID and a range key' do
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
Dynamoid::Adapter.delete('dynamoid_tests_TestTable', '123', :range_key => 2.0)
|
|
145
|
+
described_class.expects(:batch_delete_item).with(test_table => partition_range.map{|n| ["123.#{n}", 2.0]}).returns(nil)
|
|
146
|
+
described_class.delete(test_table, single_id, :range_key => 2.0)
|
|
161
147
|
end
|
|
162
148
|
|
|
163
149
|
it 'deletes through the adapter for many IDs and a range key' do
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
Dynamoid::Adapter.delete('dynamoid_tests_TestTable', ['1', '2'], :range_key => [2.0,2.0])
|
|
150
|
+
described_class.expects(:batch_delete_item).with(test_table => partition_range.map{|n| ["1.#{n}", 2.0]} + partition_range.map{|n| ["2.#{n}", 2.0]}).returns(nil)
|
|
151
|
+
described_class.delete(test_table, many_ids, :range_key => [2.0,2.0])
|
|
167
152
|
end
|
|
168
153
|
end
|
|
169
154
|
|
|
@@ -6,30 +6,30 @@ describe "Dynamoid::Associations::Association" do
|
|
|
6
6
|
Subscription.create_table
|
|
7
7
|
@magazine = Magazine.create
|
|
8
8
|
end
|
|
9
|
-
|
|
9
|
+
|
|
10
10
|
it 'returns an empty array if there are no associations' do
|
|
11
11
|
@magazine.subscriptions.should be_empty
|
|
12
12
|
end
|
|
13
|
-
|
|
13
|
+
|
|
14
14
|
it 'adds an item to an association' do
|
|
15
15
|
@subscription = Subscription.create
|
|
16
|
-
|
|
16
|
+
|
|
17
17
|
@magazine.subscriptions << @subscription
|
|
18
18
|
@magazine.subscriptions.size.should == 1
|
|
19
19
|
@magazine.subscriptions.should include @subscription
|
|
20
20
|
end
|
|
21
|
-
|
|
21
|
+
|
|
22
22
|
it 'deletes an item from an association' do
|
|
23
23
|
@subscription = Subscription.create
|
|
24
24
|
@magazine.subscriptions << @subscription
|
|
25
|
-
|
|
25
|
+
|
|
26
26
|
@magazine.subscriptions.delete(@subscription)
|
|
27
27
|
@magazine.subscriptions.size.should == 0
|
|
28
28
|
end
|
|
29
|
-
|
|
29
|
+
|
|
30
30
|
it 'creates an item from an association' do
|
|
31
31
|
@subscription = @magazine.subscriptions.create
|
|
32
|
-
|
|
32
|
+
|
|
33
33
|
@subscription.class.should == Subscription
|
|
34
34
|
@magazine.subscriptions.size.should == 1
|
|
35
35
|
@magazine.subscriptions.should include @subscription
|
|
@@ -38,7 +38,7 @@ describe "Dynamoid::Associations::Association" do
|
|
|
38
38
|
it 'returns the number of items in the association' do
|
|
39
39
|
@magazine.subscriptions.create
|
|
40
40
|
@magazine.subscriptions.size.should == 1
|
|
41
|
-
|
|
41
|
+
|
|
42
42
|
@second = @magazine.subscriptions.create
|
|
43
43
|
@magazine.subscriptions.size.should == 2
|
|
44
44
|
|
|
@@ -48,61 +48,61 @@ describe "Dynamoid::Associations::Association" do
|
|
|
48
48
|
@magazine.subscriptions = []
|
|
49
49
|
@magazine.subscriptions.size.should == 0
|
|
50
50
|
end
|
|
51
|
-
|
|
51
|
+
|
|
52
52
|
it 'assigns directly via the equals operator' do
|
|
53
53
|
@subscription = Subscription.create
|
|
54
54
|
@magazine.subscriptions = [@subscription]
|
|
55
|
-
|
|
55
|
+
|
|
56
56
|
@magazine.subscriptions.should == [@subscription]
|
|
57
57
|
end
|
|
58
|
-
|
|
58
|
+
|
|
59
59
|
it 'assigns directly via the equals operator and reflects to the target association' do
|
|
60
60
|
@subscription = Subscription.create
|
|
61
61
|
@magazine.subscriptions = [@subscription]
|
|
62
|
-
|
|
62
|
+
|
|
63
63
|
@subscription.magazine.should == @magazine
|
|
64
64
|
end
|
|
65
|
-
|
|
65
|
+
|
|
66
66
|
it 'does not assign reflection association if the reflection association does not exist' do
|
|
67
67
|
@sponsor = Sponsor.create
|
|
68
|
-
|
|
68
|
+
|
|
69
69
|
@subscription = @sponsor.subscriptions.create
|
|
70
70
|
@subscription.should_not respond_to :sponsor
|
|
71
71
|
@subscription.should_not respond_to :sponsors
|
|
72
72
|
@subscription.should_not respond_to :sponsors_ids
|
|
73
73
|
@subscription.should_not respond_to :sponsor_ids
|
|
74
74
|
end
|
|
75
|
-
|
|
75
|
+
|
|
76
76
|
it 'deletes all items from the association' do
|
|
77
77
|
@magazine.subscriptions << Subscription.create
|
|
78
78
|
@magazine.subscriptions << Subscription.create
|
|
79
79
|
@magazine.subscriptions << Subscription.create
|
|
80
|
-
|
|
80
|
+
|
|
81
81
|
@magazine.subscriptions.size.should == 3
|
|
82
|
-
|
|
82
|
+
|
|
83
83
|
@magazine.subscriptions = nil
|
|
84
84
|
@magazine.subscriptions.size.should == 0
|
|
85
85
|
end
|
|
86
|
-
|
|
86
|
+
|
|
87
87
|
it 'uses where inside an association and returns a result' do
|
|
88
88
|
@included_subscription = @magazine.subscriptions.create(:length => 10)
|
|
89
89
|
@unincldued_subscription = @magazine.subscriptions.create(:length => 8)
|
|
90
|
-
|
|
90
|
+
|
|
91
91
|
@magazine.subscriptions.where(:length => 10).all.should == [@included_subscription]
|
|
92
92
|
end
|
|
93
|
-
|
|
93
|
+
|
|
94
94
|
it 'uses where inside an association and returns an empty set' do
|
|
95
95
|
@included_subscription = @magazine.subscriptions.create(:length => 10)
|
|
96
96
|
@unincldued_subscription = @magazine.subscriptions.create(:length => 8)
|
|
97
|
-
|
|
97
|
+
|
|
98
98
|
@magazine.subscriptions.where(:length => 6).all.should be_empty
|
|
99
99
|
end
|
|
100
|
-
|
|
100
|
+
|
|
101
101
|
it 'includes enumerable' do
|
|
102
102
|
@subscription1 = @magazine.subscriptions.create
|
|
103
103
|
@subscription2 = @magazine.subscriptions.create
|
|
104
104
|
@subscription3 = @magazine.subscriptions.create
|
|
105
|
-
|
|
105
|
+
|
|
106
106
|
@magazine.subscriptions.collect(&:id).should =~ [@subscription1.id, @subscription2.id, @subscription3.id]
|
|
107
107
|
end
|
|
108
108
|
|
|
@@ -134,41 +134,41 @@ describe "Dynamoid::Associations::Association" do
|
|
|
134
134
|
#
|
|
135
135
|
# @magazine.subscriptions.instance_eval { [first, last] }.should == [@subscription1, @subscription3]
|
|
136
136
|
#end
|
|
137
|
-
|
|
137
|
+
|
|
138
138
|
it 'replaces existing associations when using the setter' do
|
|
139
139
|
@subscription1 = @magazine.subscriptions.create
|
|
140
140
|
@subscription2 = @magazine.subscriptions.create
|
|
141
141
|
@subscription3 = Subscription.create
|
|
142
|
-
|
|
142
|
+
|
|
143
143
|
@subscription1.reload.magazine_ids.should_not be_nil
|
|
144
144
|
@subscription2.reload.magazine_ids.should_not be_nil
|
|
145
145
|
|
|
146
146
|
@magazine.subscriptions = @subscription3
|
|
147
147
|
@magazine.subscriptions_ids.should == Set[@subscription3.id]
|
|
148
|
-
|
|
148
|
+
|
|
149
149
|
@subscription1.reload.magazine_ids.should be_nil
|
|
150
150
|
@subscription2.reload.magazine_ids.should be_nil
|
|
151
151
|
@subscription3.reload.magazine_ids.should == Set[@magazine.id]
|
|
152
152
|
end
|
|
153
|
-
|
|
153
|
+
|
|
154
154
|
it 'destroys all objects and removes them from the association' do
|
|
155
155
|
@subscription1 = @magazine.subscriptions.create
|
|
156
156
|
@subscription2 = @magazine.subscriptions.create
|
|
157
157
|
@subscription3 = @magazine.subscriptions.create
|
|
158
158
|
|
|
159
159
|
@magazine.subscriptions.destroy_all
|
|
160
|
-
|
|
160
|
+
|
|
161
161
|
@magazine.subscriptions.should be_empty
|
|
162
162
|
Subscription.all.should be_empty
|
|
163
163
|
end
|
|
164
|
-
|
|
164
|
+
|
|
165
165
|
it 'deletes all objects and removes them from the association' do
|
|
166
166
|
@subscription1 = @magazine.subscriptions.create
|
|
167
167
|
@subscription2 = @magazine.subscriptions.create
|
|
168
168
|
@subscription3 = @magazine.subscriptions.create
|
|
169
169
|
|
|
170
170
|
@magazine.subscriptions.delete_all
|
|
171
|
-
|
|
171
|
+
|
|
172
172
|
@magazine.subscriptions.should be_empty
|
|
173
173
|
Subscription.all.should be_empty
|
|
174
174
|
end
|
|
@@ -19,6 +19,11 @@ describe "Dynamoid::Associations::Chain" do
|
|
|
19
19
|
@chain.send(:index).should == User.indexes[[:email, :name]]
|
|
20
20
|
end
|
|
21
21
|
|
|
22
|
+
it 'makes string symbol for query keys' do
|
|
23
|
+
@chain.query = {'name' => 'Josh'}
|
|
24
|
+
@chain.send(:index).should == User.indexes[[:name]]
|
|
25
|
+
end
|
|
26
|
+
|
|
22
27
|
it 'finds matching index for a range query' do
|
|
23
28
|
@chain.query = {"created_at.gt" => @time - 1.day}
|
|
24
29
|
@chain.send(:index).should == User.indexes[[:created_at]]
|
|
@@ -51,26 +56,26 @@ describe "Dynamoid::Associations::Chain" do
|
|
|
51
56
|
|
|
52
57
|
it 'finds records with an index' do
|
|
53
58
|
@chain.query = {:name => 'Josh'}
|
|
54
|
-
@chain.send(:records_with_index).should ==
|
|
59
|
+
@chain.send(:records_with_index).should == @user
|
|
55
60
|
|
|
56
61
|
@chain.query = {:email => 'josh@joshsymonds.com'}
|
|
57
|
-
@chain.send(:records_with_index).should ==
|
|
62
|
+
@chain.send(:records_with_index).should == @user
|
|
58
63
|
|
|
59
64
|
@chain.query = {:name => 'Josh', :email => 'josh@joshsymonds.com'}
|
|
60
|
-
@chain.send(:records_with_index).should ==
|
|
65
|
+
@chain.send(:records_with_index).should == @user
|
|
61
66
|
end
|
|
62
67
|
|
|
63
68
|
it 'returns records with an index for a ranged query' do
|
|
64
69
|
@chain.query = {:name => 'Josh', "created_at.gt" => @time - 1.day}
|
|
65
|
-
@chain.send(:records_with_index).should ==
|
|
70
|
+
@chain.send(:records_with_index).should == @user
|
|
66
71
|
|
|
67
72
|
@chain.query = {:name => 'Josh', "created_at.lt" => @time + 1.day}
|
|
68
|
-
@chain.send(:records_with_index).should ==
|
|
73
|
+
@chain.send(:records_with_index).should == @user
|
|
69
74
|
end
|
|
70
75
|
|
|
71
76
|
it 'finds records without an index' do
|
|
72
77
|
@chain.query = {:password => 'Test123'}
|
|
73
|
-
@chain.send(:records_without_index).should == [@user]
|
|
78
|
+
@chain.send(:records_without_index).to_a.should == [@user]
|
|
74
79
|
end
|
|
75
80
|
|
|
76
81
|
it "doesn't crash if it finds a nil id in the index" do
|
|
@@ -94,14 +99,38 @@ describe "Dynamoid::Associations::Chain" do
|
|
|
94
99
|
@chain.collect {|u| u.name}.should == ['Josh']
|
|
95
100
|
end
|
|
96
101
|
|
|
97
|
-
it '
|
|
102
|
+
it 'uses a range query when only a hash key or range key is specified in query' do
|
|
103
|
+
# Primary key is [hash_key].
|
|
104
|
+
@chain = Dynamoid::Criteria::Chain.new(Address)
|
|
105
|
+
@chain.query = {}
|
|
106
|
+
@chain.send(:range?).should be_false
|
|
107
|
+
|
|
108
|
+
@chain = Dynamoid::Criteria::Chain.new(Address)
|
|
109
|
+
@chain.query = { :id => 'test' }
|
|
110
|
+
@chain.send(:range?).should be_true
|
|
111
|
+
|
|
112
|
+
@chain = Dynamoid::Criteria::Chain.new(Address)
|
|
113
|
+
@chain.query = { :id => 'test', :city => 'Bucharest' }
|
|
114
|
+
@chain.send(:range?).should be_false
|
|
115
|
+
|
|
116
|
+
# Primary key is [hash_key, range_key].
|
|
117
|
+
@chain = Dynamoid::Criteria::Chain.new(Tweet)
|
|
118
|
+
@chain.query = { }
|
|
119
|
+
@chain.send(:range?).should be_false
|
|
120
|
+
|
|
98
121
|
@chain = Dynamoid::Criteria::Chain.new(Tweet)
|
|
99
122
|
@chain.query = { :tweet_id => 'test' }
|
|
100
123
|
@chain.send(:range?).should be_true
|
|
101
124
|
|
|
125
|
+
@chain.query = {:tweet_id => 'test', :msg => 'hai'}
|
|
126
|
+
@chain.send(:range?).should be_false
|
|
127
|
+
|
|
102
128
|
@chain.query = {:tweet_id => 'test', :group => 'xx'}
|
|
103
129
|
@chain.send(:range?).should be_true
|
|
104
130
|
|
|
131
|
+
@chain.query = {:tweet_id => 'test', :group => 'xx', :msg => 'hai'}
|
|
132
|
+
@chain.send(:range?).should be_false
|
|
133
|
+
|
|
105
134
|
@chain.query = { :group => 'xx' }
|
|
106
135
|
@chain.send(:range?).should be_false
|
|
107
136
|
|
|
@@ -119,7 +148,7 @@ describe "Dynamoid::Associations::Chain" do
|
|
|
119
148
|
|
|
120
149
|
it 'finds tweets with a simple range query' do
|
|
121
150
|
@chain.query = { :tweet_id => "x" }
|
|
122
|
-
@chain.send(:records_with_range).size.should == 2
|
|
151
|
+
@chain.send(:records_with_range).to_a.size.should == 2
|
|
123
152
|
@chain.all.size.should == 2
|
|
124
153
|
@chain.limit(1).size.should == 1
|
|
125
154
|
end
|
|
@@ -133,7 +162,7 @@ describe "Dynamoid::Associations::Chain" do
|
|
|
133
162
|
it 'finds one specific tweet' do
|
|
134
163
|
@chain = Dynamoid::Criteria::Chain.new(Tweet)
|
|
135
164
|
@chain.query = { :tweet_id => "xx", :group => "two" }
|
|
136
|
-
@chain.send(:records_with_range).should == [@tweet3]
|
|
165
|
+
@chain.send(:records_with_range).to_a.should == [@tweet3]
|
|
137
166
|
end
|
|
138
167
|
end
|
|
139
168
|
|
|
@@ -160,4 +189,22 @@ describe "Dynamoid::Associations::Chain" do
|
|
|
160
189
|
@chain.consistent.all.size.should == 0
|
|
161
190
|
end
|
|
162
191
|
end
|
|
192
|
+
|
|
193
|
+
context 'batch queries' do
|
|
194
|
+
before do
|
|
195
|
+
@tweets = (1..4).map{|count| Tweet.create(:tweet_id => count.to_s, :group => (count % 2).to_s)}
|
|
196
|
+
@chain = Dynamoid::Criteria::Chain.new(Tweet)
|
|
197
|
+
end
|
|
198
|
+
|
|
199
|
+
it 'returns all results' do
|
|
200
|
+
@chain.batch(2).all.to_a.size.should == @tweets.size
|
|
201
|
+
end
|
|
202
|
+
|
|
203
|
+
it 'throws exception if partitioning is used with batching' do
|
|
204
|
+
previous_value = Dynamoid::Config.partitioning
|
|
205
|
+
Dynamoid::Config.partitioning = true
|
|
206
|
+
expect { @chain.batch(2) }.to raise_error
|
|
207
|
+
Dynamoid::Config.partitioning = previous_value
|
|
208
|
+
end
|
|
209
|
+
end
|
|
163
210
|
end
|