dynamoid-moda 0.7.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 +15 -0
- data/.document +5 -0
- data/.rspec +1 -0
- data/.travis.yml +7 -0
- data/Gemfile +24 -0
- data/Gemfile.lock +118 -0
- data/Gemfile_activemodel4 +24 -0
- data/Gemfile_activemodel4.lock +88 -0
- data/LICENSE.txt +20 -0
- data/README.markdown +360 -0
- data/Rakefile +93 -0
- data/VERSION +1 -0
- data/doc/.nojekyll +0 -0
- data/doc/Dynamoid.html +328 -0
- data/doc/Dynamoid/Adapter.html +1872 -0
- data/doc/Dynamoid/Adapter/AwsSdk.html +2101 -0
- data/doc/Dynamoid/Adapter/Local.html +1574 -0
- data/doc/Dynamoid/Associations.html +138 -0
- data/doc/Dynamoid/Associations/Association.html +847 -0
- data/doc/Dynamoid/Associations/BelongsTo.html +161 -0
- data/doc/Dynamoid/Associations/ClassMethods.html +766 -0
- data/doc/Dynamoid/Associations/HasAndBelongsToMany.html +167 -0
- data/doc/Dynamoid/Associations/HasMany.html +167 -0
- data/doc/Dynamoid/Associations/HasOne.html +161 -0
- data/doc/Dynamoid/Associations/ManyAssociation.html +1684 -0
- data/doc/Dynamoid/Associations/SingleAssociation.html +627 -0
- data/doc/Dynamoid/Components.html +242 -0
- data/doc/Dynamoid/Config.html +412 -0
- data/doc/Dynamoid/Config/Options.html +638 -0
- data/doc/Dynamoid/Criteria.html +138 -0
- data/doc/Dynamoid/Criteria/Chain.html +1471 -0
- data/doc/Dynamoid/Criteria/ClassMethods.html +105 -0
- data/doc/Dynamoid/Dirty.html +424 -0
- data/doc/Dynamoid/Dirty/ClassMethods.html +174 -0
- data/doc/Dynamoid/Document.html +1033 -0
- data/doc/Dynamoid/Document/ClassMethods.html +1116 -0
- data/doc/Dynamoid/Errors.html +125 -0
- data/doc/Dynamoid/Errors/ConditionalCheckFailedException.html +141 -0
- data/doc/Dynamoid/Errors/DocumentNotValid.html +221 -0
- data/doc/Dynamoid/Errors/Error.html +137 -0
- data/doc/Dynamoid/Errors/InvalidField.html +141 -0
- data/doc/Dynamoid/Errors/InvalidQuery.html +131 -0
- data/doc/Dynamoid/Errors/MissingRangeKey.html +141 -0
- data/doc/Dynamoid/Fields.html +686 -0
- data/doc/Dynamoid/Fields/ClassMethods.html +438 -0
- data/doc/Dynamoid/Finders.html +135 -0
- data/doc/Dynamoid/Finders/ClassMethods.html +943 -0
- data/doc/Dynamoid/IdentityMap.html +492 -0
- data/doc/Dynamoid/IdentityMap/ClassMethods.html +534 -0
- data/doc/Dynamoid/Indexes.html +321 -0
- data/doc/Dynamoid/Indexes/ClassMethods.html +369 -0
- data/doc/Dynamoid/Indexes/Index.html +1142 -0
- data/doc/Dynamoid/Middleware.html +115 -0
- data/doc/Dynamoid/Middleware/IdentityMap.html +264 -0
- data/doc/Dynamoid/Persistence.html +892 -0
- data/doc/Dynamoid/Persistence/ClassMethods.html +836 -0
- data/doc/Dynamoid/Validations.html +415 -0
- data/doc/_index.html +506 -0
- data/doc/class_list.html +53 -0
- data/doc/css/common.css +1 -0
- data/doc/css/full_list.css +57 -0
- data/doc/css/style.css +338 -0
- data/doc/file.LICENSE.html +73 -0
- data/doc/file.README.html +416 -0
- data/doc/file_list.html +58 -0
- data/doc/frames.html +28 -0
- data/doc/index.html +416 -0
- data/doc/js/app.js +214 -0
- data/doc/js/full_list.js +178 -0
- data/doc/js/jquery.js +4 -0
- data/doc/method_list.html +1144 -0
- data/doc/top-level-namespace.html +112 -0
- data/dynamoid-moda.gemspec +210 -0
- data/dynamoid.gemspec +208 -0
- data/lib/dynamoid.rb +46 -0
- data/lib/dynamoid/adapter.rb +267 -0
- data/lib/dynamoid/adapter/aws_sdk.rb +309 -0
- data/lib/dynamoid/associations.rb +106 -0
- data/lib/dynamoid/associations/association.rb +105 -0
- data/lib/dynamoid/associations/belongs_to.rb +44 -0
- data/lib/dynamoid/associations/has_and_belongs_to_many.rb +40 -0
- data/lib/dynamoid/associations/has_many.rb +39 -0
- data/lib/dynamoid/associations/has_one.rb +39 -0
- data/lib/dynamoid/associations/many_association.rb +191 -0
- data/lib/dynamoid/associations/single_association.rb +69 -0
- data/lib/dynamoid/components.rb +37 -0
- data/lib/dynamoid/config.rb +57 -0
- data/lib/dynamoid/config/options.rb +78 -0
- data/lib/dynamoid/criteria.rb +29 -0
- data/lib/dynamoid/criteria/chain.rb +326 -0
- data/lib/dynamoid/dirty.rb +47 -0
- data/lib/dynamoid/document.rb +199 -0
- data/lib/dynamoid/errors.rb +28 -0
- data/lib/dynamoid/fields.rb +138 -0
- data/lib/dynamoid/finders.rb +133 -0
- data/lib/dynamoid/identity_map.rb +96 -0
- data/lib/dynamoid/indexes.rb +69 -0
- data/lib/dynamoid/indexes/index.rb +103 -0
- data/lib/dynamoid/middleware/identity_map.rb +16 -0
- data/lib/dynamoid/persistence.rb +292 -0
- data/lib/dynamoid/validations.rb +36 -0
- data/spec/app/models/address.rb +13 -0
- data/spec/app/models/camel_case.rb +34 -0
- data/spec/app/models/car.rb +6 -0
- data/spec/app/models/magazine.rb +11 -0
- data/spec/app/models/message.rb +9 -0
- data/spec/app/models/nuclear_submarine.rb +5 -0
- data/spec/app/models/sponsor.rb +8 -0
- data/spec/app/models/subscription.rb +12 -0
- data/spec/app/models/tweet.rb +12 -0
- data/spec/app/models/user.rb +26 -0
- data/spec/app/models/vehicle.rb +7 -0
- data/spec/dynamoid/adapter/aws_sdk_spec.rb +376 -0
- data/spec/dynamoid/adapter_spec.rb +155 -0
- data/spec/dynamoid/associations/association_spec.rb +194 -0
- data/spec/dynamoid/associations/belongs_to_spec.rb +71 -0
- data/spec/dynamoid/associations/has_and_belongs_to_many_spec.rb +47 -0
- data/spec/dynamoid/associations/has_many_spec.rb +42 -0
- data/spec/dynamoid/associations/has_one_spec.rb +45 -0
- data/spec/dynamoid/associations_spec.rb +16 -0
- data/spec/dynamoid/config_spec.rb +27 -0
- data/spec/dynamoid/criteria/chain_spec.rb +210 -0
- data/spec/dynamoid/criteria_spec.rb +75 -0
- data/spec/dynamoid/dirty_spec.rb +57 -0
- data/spec/dynamoid/document_spec.rb +180 -0
- data/spec/dynamoid/fields_spec.rb +156 -0
- data/spec/dynamoid/finders_spec.rb +147 -0
- data/spec/dynamoid/identity_map_spec.rb +45 -0
- data/spec/dynamoid/indexes/index_spec.rb +104 -0
- data/spec/dynamoid/indexes_spec.rb +25 -0
- data/spec/dynamoid/persistence_spec.rb +301 -0
- data/spec/dynamoid/validations_spec.rb +36 -0
- data/spec/dynamoid_spec.rb +14 -0
- data/spec/spec_helper.rb +55 -0
- data/spec/support/with_partitioning.rb +15 -0
- metadata +363 -0
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + '/../../spec_helper')
|
|
2
|
+
|
|
3
|
+
describe "Dynamoid::Associations::HasMany" do
|
|
4
|
+
|
|
5
|
+
before do
|
|
6
|
+
@magazine = Magazine.create
|
|
7
|
+
@user = User.create
|
|
8
|
+
@camel_case = CamelCase.create
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
it 'determines equality from its records' do
|
|
12
|
+
@subscription = @magazine.subscriptions.create
|
|
13
|
+
|
|
14
|
+
@magazine.subscriptions.should == @subscription
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
it 'determines target association correctly' do
|
|
18
|
+
@magazine.subscriptions.send(:target_association).should == :magazine
|
|
19
|
+
@user.books.send(:target_association).should == :owner
|
|
20
|
+
@camel_case.users.send(:target_association).should == :camel_case
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
it 'determins target class correctly' do
|
|
24
|
+
@magazine.subscriptions.send(:target_class).should == Subscription
|
|
25
|
+
@user.books.send(:target_class).should == Magazine
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
it 'determines target attribute' do
|
|
29
|
+
@magazine.subscriptions.send(:target_attribute).should == :magazine_ids
|
|
30
|
+
@user.books.send(:target_attribute).should == :owner_ids
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
it 'associates belongs_to automatically' do
|
|
34
|
+
@subscription = @magazine.subscriptions.create
|
|
35
|
+
|
|
36
|
+
@subscription.magazine.should == @magazine
|
|
37
|
+
|
|
38
|
+
@magazine = @user.books.create
|
|
39
|
+
@magazine.owner.should == @user
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
end
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + '/../../spec_helper')
|
|
2
|
+
|
|
3
|
+
describe "Dynamoid::Associations::HasOne" do
|
|
4
|
+
|
|
5
|
+
before do
|
|
6
|
+
@magazine = Magazine.create
|
|
7
|
+
@user = User.create
|
|
8
|
+
@camel_case = CamelCase.create
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
it 'determines nil if it has no associated record' do
|
|
12
|
+
@magazine.sponsor.should be_nil
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
it 'determines target association correctly' do
|
|
16
|
+
@camel_case.sponsor.send(:target_association).should == :camel_case
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
it 'returns only one object when associated' do
|
|
20
|
+
@magazine.sponsor.create
|
|
21
|
+
|
|
22
|
+
@magazine.sponsor.should_not be_a_kind_of Array
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
it 'delegates equality to its source record' do
|
|
26
|
+
@sponsor = @magazine.sponsor.create
|
|
27
|
+
|
|
28
|
+
@magazine.sponsor.should == @sponsor
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
it 'is equal from its target record' do
|
|
32
|
+
@sponsor = @magazine.sponsor.create
|
|
33
|
+
|
|
34
|
+
@magazine.sponsor.should == @sponsor
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
it 'associates belongs_to automatically' do
|
|
38
|
+
@sponsor = @magazine.sponsor.create
|
|
39
|
+
@sponsor.magazine.should == @magazine
|
|
40
|
+
@magazine.sponsor.should == @sponsor
|
|
41
|
+
|
|
42
|
+
@subscription = @user.monthly.create
|
|
43
|
+
@subscription.customer.should == @user
|
|
44
|
+
end
|
|
45
|
+
end
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
|
|
2
|
+
|
|
3
|
+
describe "Dynamoid::Associations" do
|
|
4
|
+
|
|
5
|
+
before do
|
|
6
|
+
@magazine = Magazine.create
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
it 'defines a getter' do
|
|
10
|
+
@magazine.should respond_to :subscriptions
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
it 'defines a setter' do
|
|
14
|
+
@magazine.should respond_to :subscriptions=
|
|
15
|
+
end
|
|
16
|
+
end
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
|
|
2
|
+
|
|
3
|
+
describe "Dynamoid::Config" do
|
|
4
|
+
|
|
5
|
+
before(:each) do
|
|
6
|
+
Dynamoid::Config.reset_namespace
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
after(:each) do
|
|
10
|
+
Dynamoid.config {|config| config.namespace = 'dynamoid_tests'}
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
it 'returns a namespace for non-Rails apps' do
|
|
14
|
+
Dynamoid::Config.namespace.should == 'dynamoid'
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
it 'returns a namespace for Rails apps' do
|
|
18
|
+
class Rails; end
|
|
19
|
+
Rails.stubs(:application => stubs(:class => stubs(:parent_name => 'TestApp')))
|
|
20
|
+
Rails.stubs(:env => 'development')
|
|
21
|
+
Dynamoid::Config.send(:option, :namespace, :default => defined?(Rails) ? "dynamoid_#{Rails.application.class.parent_name}_#{Rails.env}" : "dynamoid")
|
|
22
|
+
|
|
23
|
+
# TODO Make this return what we actually expect
|
|
24
|
+
Dynamoid::Config.namespace.should == "dynamoid_Mocha_development"
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
end
|
|
@@ -0,0 +1,210 @@
|
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + '/../../spec_helper')
|
|
2
|
+
|
|
3
|
+
describe "Dynamoid::Associations::Chain" do
|
|
4
|
+
|
|
5
|
+
before(:each) do
|
|
6
|
+
@time = DateTime.now
|
|
7
|
+
@user = User.create(:name => 'Josh', :email => 'josh@joshsymonds.com', :password => 'Test123')
|
|
8
|
+
@chain = Dynamoid::Criteria::Chain.new(User)
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
it 'finds matching index for a query' do
|
|
12
|
+
@chain.query = {:name => 'Josh'}
|
|
13
|
+
@chain.send(:index).should == User.indexes[[:name]]
|
|
14
|
+
|
|
15
|
+
@chain.query = {:email => 'josh@joshsymonds.com'}
|
|
16
|
+
@chain.send(:index).should == User.indexes[[:email]]
|
|
17
|
+
|
|
18
|
+
@chain.query = {:name => 'Josh', :email => 'josh@joshsymonds.com'}
|
|
19
|
+
@chain.send(:index).should == User.indexes[[:email, :name]]
|
|
20
|
+
end
|
|
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
|
+
|
|
27
|
+
it 'finds matching index for a range query' do
|
|
28
|
+
@chain.query = {"created_at.gt" => @time - 1.day}
|
|
29
|
+
@chain.send(:index).should == User.indexes[[:created_at]]
|
|
30
|
+
|
|
31
|
+
@chain.query = {:name => 'Josh', "created_at.lt" => @time - 1.day}
|
|
32
|
+
@chain.send(:index).should == User.indexes[[:created_at, :name]]
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
it 'does not find an index if there is not an appropriate one' do
|
|
36
|
+
@chain.query = {:password => 'Test123'}
|
|
37
|
+
@chain.send(:index).should be_nil
|
|
38
|
+
|
|
39
|
+
@chain.query = {:password => 'Test123', :created_at => @time}
|
|
40
|
+
@chain.send(:index).should be_nil
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
it 'returns values for index for a query' do
|
|
44
|
+
@chain.query = {:name => 'Josh'}
|
|
45
|
+
@chain.send(:index_query).should == {:hash_value => 'Josh'}
|
|
46
|
+
|
|
47
|
+
@chain.query = {:email => 'josh@joshsymonds.com'}
|
|
48
|
+
@chain.send(:index_query).should == {:hash_value => 'josh@joshsymonds.com'}
|
|
49
|
+
|
|
50
|
+
@chain.query = {:name => 'Josh', :email => 'josh@joshsymonds.com'}
|
|
51
|
+
@chain.send(:index_query).should == {:hash_value => 'josh@joshsymonds.com.Josh'}
|
|
52
|
+
|
|
53
|
+
@chain.query = {:name => 'Josh', 'created_at.gt' => @time}
|
|
54
|
+
@chain.send(:index_query).should == {:hash_value => 'Josh', :range_greater_than => @time.to_f}
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
it 'finds records with an index' do
|
|
58
|
+
@chain.query = {:name => 'Josh'}
|
|
59
|
+
@chain.send(:records_with_index).should == @user
|
|
60
|
+
|
|
61
|
+
@chain.query = {:email => 'josh@joshsymonds.com'}
|
|
62
|
+
@chain.send(:records_with_index).should == @user
|
|
63
|
+
|
|
64
|
+
@chain.query = {:name => 'Josh', :email => 'josh@joshsymonds.com'}
|
|
65
|
+
@chain.send(:records_with_index).should == @user
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
it 'returns records with an index for a ranged query' do
|
|
69
|
+
@chain.query = {:name => 'Josh', "created_at.gt" => @time - 1.day}
|
|
70
|
+
@chain.send(:records_with_index).should == @user
|
|
71
|
+
|
|
72
|
+
@chain.query = {:name => 'Josh', "created_at.lt" => @time + 1.day}
|
|
73
|
+
@chain.send(:records_with_index).should == @user
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
it 'finds records without an index' do
|
|
77
|
+
@chain.query = {:password => 'Test123'}
|
|
78
|
+
@chain.send(:records_without_index).to_a.should == [@user]
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
it "doesn't crash if it finds a nil id in the index" do
|
|
82
|
+
@chain.query = {:name => 'Josh', "created_at.gt" => @time - 1.day}
|
|
83
|
+
Dynamoid::Adapter.expects(:query).
|
|
84
|
+
with("dynamoid_tests_index_user_created_ats_and_names", kind_of(Hash)).
|
|
85
|
+
returns([{ids: nil}, {ids: Set.new([42])}])
|
|
86
|
+
@chain.send(:ids_from_index).should == Set.new([42])
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
it 'defines each' do
|
|
90
|
+
@chain.query = {:name => 'Josh'}
|
|
91
|
+
@chain.each {|u| u.update_attribute(:name, 'Justin')}
|
|
92
|
+
|
|
93
|
+
User.find(@user.id).name.should == 'Justin'
|
|
94
|
+
end
|
|
95
|
+
|
|
96
|
+
it 'includes Enumerable' do
|
|
97
|
+
@chain.query = {:name => 'Josh'}
|
|
98
|
+
|
|
99
|
+
@chain.collect {|u| u.name}.should == ['Josh']
|
|
100
|
+
end
|
|
101
|
+
|
|
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
|
+
|
|
121
|
+
@chain = Dynamoid::Criteria::Chain.new(Tweet)
|
|
122
|
+
@chain.query = { :tweet_id => 'test' }
|
|
123
|
+
@chain.send(:range?).should be_true
|
|
124
|
+
|
|
125
|
+
@chain.query = {:tweet_id => 'test', :msg => 'hai'}
|
|
126
|
+
@chain.send(:range?).should be_false
|
|
127
|
+
|
|
128
|
+
@chain.query = {:tweet_id => 'test', :group => 'xx'}
|
|
129
|
+
@chain.send(:range?).should be_true
|
|
130
|
+
|
|
131
|
+
@chain.query = {:tweet_id => 'test', :group => 'xx', :msg => 'hai'}
|
|
132
|
+
@chain.send(:range?).should be_false
|
|
133
|
+
|
|
134
|
+
@chain.query = { :group => 'xx' }
|
|
135
|
+
@chain.send(:range?).should be_false
|
|
136
|
+
|
|
137
|
+
@chain.query = { :group => 'xx', :msg => 'hai' }
|
|
138
|
+
@chain.send(:range?).should be_false
|
|
139
|
+
end
|
|
140
|
+
|
|
141
|
+
context 'range queries' do
|
|
142
|
+
before do
|
|
143
|
+
@tweet1 = Tweet.create(:tweet_id => "x", :group => "one")
|
|
144
|
+
@tweet2 = Tweet.create(:tweet_id => "x", :group => "two")
|
|
145
|
+
@tweet3 = Tweet.create(:tweet_id => "xx", :group => "two")
|
|
146
|
+
@chain = Dynamoid::Criteria::Chain.new(Tweet)
|
|
147
|
+
end
|
|
148
|
+
|
|
149
|
+
it 'finds tweets with a simple range query' do
|
|
150
|
+
@chain.query = { :tweet_id => "x" }
|
|
151
|
+
@chain.send(:records_with_range).to_a.size.should == 2
|
|
152
|
+
@chain.all.size.should == 2
|
|
153
|
+
@chain.limit(1).size.should == 1
|
|
154
|
+
end
|
|
155
|
+
|
|
156
|
+
it 'finds tweets with a start' do
|
|
157
|
+
@chain.query = { :tweet_id => "x" }
|
|
158
|
+
@chain.start(@tweet1)
|
|
159
|
+
@chain.all.should =~ [@tweet2]
|
|
160
|
+
end
|
|
161
|
+
|
|
162
|
+
it 'finds one specific tweet' do
|
|
163
|
+
@chain = Dynamoid::Criteria::Chain.new(Tweet)
|
|
164
|
+
@chain.query = { :tweet_id => "xx", :group => "two" }
|
|
165
|
+
@chain.send(:records_with_range).to_a.should == [@tweet3]
|
|
166
|
+
end
|
|
167
|
+
end
|
|
168
|
+
|
|
169
|
+
context 'destroy alls' do
|
|
170
|
+
before do
|
|
171
|
+
@tweet1 = Tweet.create(:tweet_id => "x", :group => "one")
|
|
172
|
+
@tweet2 = Tweet.create(:tweet_id => "x", :group => "two")
|
|
173
|
+
@tweet3 = Tweet.create(:tweet_id => "xx", :group => "two")
|
|
174
|
+
@chain = Dynamoid::Criteria::Chain.new(Tweet)
|
|
175
|
+
end
|
|
176
|
+
|
|
177
|
+
it 'destroys tweet with a range simple range query' do
|
|
178
|
+
@chain.query = { :tweet_id => "x" }
|
|
179
|
+
@chain.all.size.should == 2
|
|
180
|
+
@chain.destroy_all
|
|
181
|
+
@chain.consistent.all.size.should == 0
|
|
182
|
+
end
|
|
183
|
+
|
|
184
|
+
it 'deletes one specific tweet with range' do
|
|
185
|
+
@chain = Dynamoid::Criteria::Chain.new(Tweet)
|
|
186
|
+
@chain.query = { :tweet_id => "xx", :group => "two" }
|
|
187
|
+
@chain.all.size.should == 1
|
|
188
|
+
@chain.destroy_all
|
|
189
|
+
@chain.consistent.all.size.should == 0
|
|
190
|
+
end
|
|
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
|
|
210
|
+
end
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
|
|
2
|
+
|
|
3
|
+
describe "Dynamoid::Criteria" do
|
|
4
|
+
before(:all) do
|
|
5
|
+
Magazine.create_table
|
|
6
|
+
end
|
|
7
|
+
|
|
8
|
+
before do
|
|
9
|
+
@user1 = User.create(:name => 'Josh', :email => 'josh@joshsymonds.com')
|
|
10
|
+
@user2 = User.create(:name => 'Justin', :email => 'justin@joshsymonds.com')
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
it 'finds first using where' do
|
|
14
|
+
User.where(:name => 'Josh').first.should == @user1
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
it 'finds all using where' do
|
|
18
|
+
User.where(:name => 'Josh').all.should == [@user1]
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
it 'returns all records' do
|
|
22
|
+
User.all.should =~ [@user1, @user2]
|
|
23
|
+
User.all.first.new_record.should be_false
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
it 'returns empty attributes for where' do
|
|
27
|
+
Magazine.where(:name => 'Josh').all.should == []
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
it 'returns empty attributes for all' do
|
|
31
|
+
Magazine.all.should == []
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
it 'passes each to all members' do
|
|
35
|
+
User.each do |u|
|
|
36
|
+
u.id.should == @user1.id || @user2.id
|
|
37
|
+
u.new_record.should be_false
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
it 'returns n records' do
|
|
42
|
+
User.limit(1).size.should eq(1)
|
|
43
|
+
5.times { |i| User.create(:name => 'Josh', :email => 'josh_#{i}@joshsymonds.com') }
|
|
44
|
+
User.where(:name => 'Josh').all.size.should == 6
|
|
45
|
+
User.where(:name => 'Josh').limit(2).size.should == 2
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
# TODO This test is broken using the AWS SDK adapter.
|
|
49
|
+
#it 'start with a record' do
|
|
50
|
+
# 5.times { |i| User.create(:name => 'Josh', :email => 'josh_#{i}@joshsymonds.com') }
|
|
51
|
+
# all = User.all
|
|
52
|
+
# User.start(all[3]).all.should eq(all[4..-1])
|
|
53
|
+
#
|
|
54
|
+
# all = User.where(:name => 'Josh').all
|
|
55
|
+
# User.where(:name => 'Josh').start(all[3]).all.should eq(all[4..-1])
|
|
56
|
+
#end
|
|
57
|
+
|
|
58
|
+
it 'send consistent option to adapter' do
|
|
59
|
+
Dynamoid::Adapter.expects(:get_item).with { |table_name, key, options| options[:consistent_read] == true }
|
|
60
|
+
User.where(:name => 'x').consistent.first
|
|
61
|
+
|
|
62
|
+
Dynamoid::Adapter.expects(:query).with { |table_name, options| options[:consistent_read] == true }.returns([])
|
|
63
|
+
Tweet.where(:tweet_id => 'xx', :group => 'two').consistent.all
|
|
64
|
+
|
|
65
|
+
Dynamoid::Adapter.expects(:query).with { |table_name, options| options[:consistent_read] == false }.returns([])
|
|
66
|
+
Tweet.where(:tweet_id => 'xx', :group => 'two').all
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
it 'raises exception when consistent_read is used with scan' do
|
|
70
|
+
expect do
|
|
71
|
+
User.where(:password => 'password').consistent.first
|
|
72
|
+
end.to raise_error(Dynamoid::Errors::InvalidQuery)
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
end
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
|
|
2
|
+
|
|
3
|
+
describe 'Dynamoid::Dirty' do
|
|
4
|
+
|
|
5
|
+
context 'changes' do
|
|
6
|
+
it 'should be empty' do
|
|
7
|
+
tweet = Tweet.new
|
|
8
|
+
tweet.msg_changed?.should be_false
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
it 'should not be empty' do
|
|
12
|
+
tweet = Tweet.new(:tweet_id => "1", :group => 'abc')
|
|
13
|
+
tweet.changed?.should be_true
|
|
14
|
+
tweet.group_was.should be_nil
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
it 'should be empty when loaded from database' do
|
|
18
|
+
Tweet.create!(:tweet_id => "1", :group => 'abc')
|
|
19
|
+
tweet = Tweet.where(:tweet_id => "1", :group => 'abc').first
|
|
20
|
+
tweet.changed?.should be_false
|
|
21
|
+
tweet.group = 'abc'
|
|
22
|
+
tweet.reload
|
|
23
|
+
tweet.changed?.should be_false
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
it 'should be empty after an update' do
|
|
27
|
+
tweet = Tweet.create!(:tweet_id => "1", :group => 'abc')
|
|
28
|
+
tweet.update! do |t|
|
|
29
|
+
t.set(msg: "foo")
|
|
30
|
+
end
|
|
31
|
+
tweet.changed?.should be_false
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
it 'track changes after saves' do
|
|
35
|
+
tweet = Tweet.new(:tweet_id => "1", :group => 'abc')
|
|
36
|
+
tweet.save!
|
|
37
|
+
tweet.changed?.should be_false
|
|
38
|
+
|
|
39
|
+
tweet.user_name = 'xyz'
|
|
40
|
+
tweet.user_name_changed?.should be_true
|
|
41
|
+
tweet.user_name_was.should be_nil
|
|
42
|
+
tweet.save!
|
|
43
|
+
|
|
44
|
+
tweet.user_name_changed?.should be_false
|
|
45
|
+
tweet.user_name = 'abc'
|
|
46
|
+
tweet.user_name_was.should == 'xyz'
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
it 'clear changes on save' do
|
|
50
|
+
tweet = Tweet.new(:tweet_id => "1", :group => 'abc')
|
|
51
|
+
tweet.group = 'xyz'
|
|
52
|
+
tweet.group_changed?.should be_true
|
|
53
|
+
tweet.save!
|
|
54
|
+
tweet.group_changed?.should be_false
|
|
55
|
+
end
|
|
56
|
+
end
|
|
57
|
+
end
|