adept_dynamoid 0.5.0.6
Sign up to get free protection for your applications and to get access to all the features.
- data/.document +5 -0
- data/.rspec +1 -0
- data/Dynamoid.gemspec +193 -0
- data/Gemfile +23 -0
- data/Gemfile.lock +86 -0
- data/LICENSE.txt +20 -0
- data/README.markdown +265 -0
- data/Rakefile +62 -0
- data/VERSION +1 -0
- data/doc/.nojekyll +0 -0
- data/doc/Dynamoid.html +312 -0
- data/doc/Dynamoid/Adapter.html +1385 -0
- data/doc/Dynamoid/Adapter/AwsSdk.html +1585 -0
- data/doc/Dynamoid/Adapter/Local.html +1574 -0
- data/doc/Dynamoid/Associations.html +131 -0
- data/doc/Dynamoid/Associations/Association.html +794 -0
- data/doc/Dynamoid/Associations/BelongsTo.html +158 -0
- data/doc/Dynamoid/Associations/ClassMethods.html +723 -0
- data/doc/Dynamoid/Associations/HasAndBelongsToMany.html +164 -0
- data/doc/Dynamoid/Associations/HasMany.html +164 -0
- data/doc/Dynamoid/Associations/HasOne.html +158 -0
- data/doc/Dynamoid/Associations/ManyAssociation.html +1640 -0
- data/doc/Dynamoid/Associations/SingleAssociation.html +598 -0
- data/doc/Dynamoid/Components.html +204 -0
- data/doc/Dynamoid/Config.html +395 -0
- data/doc/Dynamoid/Config/Options.html +609 -0
- data/doc/Dynamoid/Criteria.html +131 -0
- data/doc/Dynamoid/Criteria/Chain.html +1063 -0
- data/doc/Dynamoid/Criteria/ClassMethods.html +98 -0
- data/doc/Dynamoid/Document.html +666 -0
- data/doc/Dynamoid/Document/ClassMethods.html +937 -0
- data/doc/Dynamoid/Errors.html +118 -0
- data/doc/Dynamoid/Errors/DocumentNotValid.html +210 -0
- data/doc/Dynamoid/Errors/Error.html +130 -0
- data/doc/Dynamoid/Errors/InvalidField.html +133 -0
- data/doc/Dynamoid/Errors/MissingRangeKey.html +133 -0
- data/doc/Dynamoid/Fields.html +669 -0
- data/doc/Dynamoid/Fields/ClassMethods.html +309 -0
- data/doc/Dynamoid/Finders.html +128 -0
- data/doc/Dynamoid/Finders/ClassMethods.html +516 -0
- data/doc/Dynamoid/Indexes.html +308 -0
- data/doc/Dynamoid/Indexes/ClassMethods.html +353 -0
- data/doc/Dynamoid/Indexes/Index.html +1104 -0
- data/doc/Dynamoid/Persistence.html +651 -0
- data/doc/Dynamoid/Persistence/ClassMethods.html +670 -0
- data/doc/Dynamoid/Validations.html +399 -0
- data/doc/_index.html +461 -0
- data/doc/class_list.html +47 -0
- data/doc/css/common.css +1 -0
- data/doc/css/full_list.css +55 -0
- data/doc/css/style.css +322 -0
- data/doc/file.LICENSE.html +66 -0
- data/doc/file.README.html +312 -0
- data/doc/file_list.html +52 -0
- data/doc/frames.html +13 -0
- data/doc/index.html +312 -0
- data/doc/js/app.js +205 -0
- data/doc/js/full_list.js +173 -0
- data/doc/js/jquery.js +16 -0
- data/doc/method_list.html +1238 -0
- data/doc/top-level-namespace.html +105 -0
- data/lib/dynamoid.rb +47 -0
- data/lib/dynamoid/adapter.rb +177 -0
- data/lib/dynamoid/adapter/aws_sdk.rb +223 -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 +36 -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 +243 -0
- data/lib/dynamoid/dirty.rb +41 -0
- data/lib/dynamoid/document.rb +184 -0
- data/lib/dynamoid/errors.rb +28 -0
- data/lib/dynamoid/fields.rb +130 -0
- data/lib/dynamoid/finders.rb +131 -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 +247 -0
- data/lib/dynamoid/validations.rb +36 -0
- data/spec/app/models/address.rb +10 -0
- data/spec/app/models/camel_case.rb +24 -0
- data/spec/app/models/magazine.rb +11 -0
- data/spec/app/models/message.rb +9 -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/dynamoid/adapter/aws_sdk_spec.rb +186 -0
- data/spec/dynamoid/adapter_spec.rb +117 -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 +140 -0
- data/spec/dynamoid/criteria_spec.rb +72 -0
- data/spec/dynamoid/dirty_spec.rb +49 -0
- data/spec/dynamoid/document_spec.rb +118 -0
- data/spec/dynamoid/fields_spec.rb +127 -0
- data/spec/dynamoid/finders_spec.rb +135 -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 +176 -0
- data/spec/dynamoid/validations_spec.rb +36 -0
- data/spec/dynamoid_spec.rb +9 -0
- data/spec/spec_helper.rb +50 -0
- metadata +376 -0
@@ -0,0 +1,135 @@
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
|
2
|
+
|
3
|
+
describe "Dynamoid::Finders" do
|
4
|
+
|
5
|
+
before do
|
6
|
+
@address = Address.create(:city => 'Chicago')
|
7
|
+
end
|
8
|
+
|
9
|
+
it 'finds an existing address' do
|
10
|
+
found = Address.find(@address.id)
|
11
|
+
|
12
|
+
found.should == @address
|
13
|
+
found.city.should == 'Chicago'
|
14
|
+
end
|
15
|
+
|
16
|
+
it 'is not a new object' do
|
17
|
+
found = Address.find(@address.id)
|
18
|
+
|
19
|
+
found.new_record.should_not be_true
|
20
|
+
end
|
21
|
+
|
22
|
+
it 'returns nil when nothing is found' do
|
23
|
+
Address.find('1234').should be_nil
|
24
|
+
end
|
25
|
+
|
26
|
+
it 'finds multiple ids' do
|
27
|
+
@address2 = Address.create(:city => 'Illinois')
|
28
|
+
|
29
|
+
Address.find(@address.id, @address2.id).should include @address, @address2
|
30
|
+
end
|
31
|
+
|
32
|
+
it 'sends consistent option to the adapter' do
|
33
|
+
Dynamoid::Adapter.expects(:get_item).with { |table_name, key, options| options[:consistent_read] == true }
|
34
|
+
Address.find('x', :consistent_read => true)
|
35
|
+
end
|
36
|
+
|
37
|
+
context 'with users' do
|
38
|
+
before do
|
39
|
+
User.create_indexes
|
40
|
+
end
|
41
|
+
|
42
|
+
it 'finds using method_missing for attributes' do
|
43
|
+
array = Address.find_by_city('Chicago')
|
44
|
+
|
45
|
+
array.should == @address
|
46
|
+
end
|
47
|
+
|
48
|
+
it 'finds using method_missing for multiple attributes' do
|
49
|
+
@user = User.create(:name => 'Josh', :email => 'josh@joshsymonds.com')
|
50
|
+
|
51
|
+
array = User.find_all_by_name_and_email('Josh', 'josh@joshsymonds.com')
|
52
|
+
|
53
|
+
array.should == [@user]
|
54
|
+
end
|
55
|
+
|
56
|
+
it 'finds using method_missing for single attributes and multiple results' do
|
57
|
+
@user1 = User.create(:name => 'Josh', :email => 'josh@joshsymonds.com')
|
58
|
+
@user2 = User.create(:name => 'Josh', :email => 'josh@joshsymonds.com')
|
59
|
+
|
60
|
+
array = User.find_all_by_name('Josh')
|
61
|
+
|
62
|
+
array.size.should == 2
|
63
|
+
array.should include @user1
|
64
|
+
array.should include @user2
|
65
|
+
end
|
66
|
+
|
67
|
+
it 'finds using method_missing for multiple attributes and multiple results' do
|
68
|
+
@user1 = User.create(:name => 'Josh', :email => 'josh@joshsymonds.com')
|
69
|
+
@user2 = User.create(:name => 'Josh', :email => 'josh@joshsymonds.com')
|
70
|
+
|
71
|
+
array = User.find_all_by_name_and_email('Josh', 'josh@joshsymonds.com')
|
72
|
+
|
73
|
+
array.size.should == 2
|
74
|
+
array.should include @user1
|
75
|
+
array.should include @user2
|
76
|
+
end
|
77
|
+
|
78
|
+
it 'finds using method_missing for multiple attributes and no results' do
|
79
|
+
@user1 = User.create(:name => 'Josh', :email => 'josh@joshsymonds.com')
|
80
|
+
@user2 = User.create(:name => 'Justin', :email => 'justin@joshsymonds.com')
|
81
|
+
|
82
|
+
array = User.find_all_by_name_and_email('Gaga','josh@joshsymonds.com')
|
83
|
+
|
84
|
+
array.should be_empty
|
85
|
+
end
|
86
|
+
|
87
|
+
it 'finds using method_missing for a single attribute and no results' do
|
88
|
+
@user1 = User.create(:name => 'Josh', :email => 'josh@joshsymonds.com')
|
89
|
+
@user2 = User.create(:name => 'Justin', :email => 'justin@joshsymonds.com')
|
90
|
+
|
91
|
+
array = User.find_all_by_name('Gaga')
|
92
|
+
|
93
|
+
array.should be_empty
|
94
|
+
end
|
95
|
+
|
96
|
+
it 'should find on a query that is not indexed' do
|
97
|
+
@user = User.create(:password => 'Test')
|
98
|
+
|
99
|
+
array = User.find_all_by_password('Test')
|
100
|
+
|
101
|
+
array.should == [@user]
|
102
|
+
end
|
103
|
+
|
104
|
+
it 'should find on a query on multiple attributes that are not indexed' do
|
105
|
+
@user = User.create(:password => 'Test', :name => 'Josh')
|
106
|
+
|
107
|
+
array = User.find_all_by_password_and_name('Test', 'Josh')
|
108
|
+
|
109
|
+
array.should == [@user]
|
110
|
+
end
|
111
|
+
|
112
|
+
it 'should return an empty array when fields exist but nothing is found' do
|
113
|
+
array = User.find_all_by_password('Test')
|
114
|
+
|
115
|
+
array.should be_empty
|
116
|
+
end
|
117
|
+
|
118
|
+
end
|
119
|
+
|
120
|
+
context 'find_all' do
|
121
|
+
it 'should return a array of users' do
|
122
|
+
users = (1..10).map { User.create }
|
123
|
+
User.find_all(users.map(&:id)).should eq(users)
|
124
|
+
end
|
125
|
+
|
126
|
+
it 'should return a array of tweets' do
|
127
|
+
tweets = (1..10).map { |i| Tweet.create(:tweet_id => "#{i}", :group => "group_#{i}") }
|
128
|
+
Tweet.find_all(tweets.map { |t| [t.tweet_id, t.group] }).should eq(tweets)
|
129
|
+
end
|
130
|
+
|
131
|
+
it 'should return an empty array' do
|
132
|
+
User.find_all([]).should eq([])
|
133
|
+
end
|
134
|
+
end
|
135
|
+
end
|
@@ -0,0 +1,45 @@
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
|
2
|
+
|
3
|
+
describe "Dynamoid::IdentityMap" do
|
4
|
+
before :each do
|
5
|
+
Dynamoid::Config.identity_map = true
|
6
|
+
end
|
7
|
+
|
8
|
+
after :each do
|
9
|
+
Dynamoid::Config.identity_map = false
|
10
|
+
end
|
11
|
+
|
12
|
+
context 'object identity' do
|
13
|
+
it 'maintains a single object' do
|
14
|
+
tweet = Tweet.create(:tweet_id => "x", :group => "one")
|
15
|
+
tweet1 = Tweet.where(:tweet_id => "x", :group => "one").first
|
16
|
+
tweet.should equal(tweet1)
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
context 'cache' do
|
21
|
+
it 'uses cache' do
|
22
|
+
tweet = Tweet.create(:tweet_id => "x", :group => "one")
|
23
|
+
Dynamoid::Adapter.expects(:read).never
|
24
|
+
tweet1 = Tweet.find_by_id("x", :range_key => "one")
|
25
|
+
tweet.should equal(tweet1)
|
26
|
+
end
|
27
|
+
|
28
|
+
it 'clears cache on delete' do
|
29
|
+
tweet = Tweet.create(:tweet_id => "x", :group => "one")
|
30
|
+
tweet.delete
|
31
|
+
Tweet.find_by_id("x", :range_key => "one").should be_nil
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
context 'clear' do
|
36
|
+
it 'clears the identiy map' do
|
37
|
+
Tweet.create(:tweet_id => "x", :group => "one")
|
38
|
+
Tweet.create(:tweet_id => "x", :group => "two")
|
39
|
+
|
40
|
+
Tweet.identity_map.size.should eq(2)
|
41
|
+
Dynamoid::IdentityMap.clear
|
42
|
+
Tweet.identity_map.size.should eq(0)
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
@@ -0,0 +1,104 @@
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + '/../../spec_helper')
|
2
|
+
|
3
|
+
describe "Dynamoid::Indexes::Index" do
|
4
|
+
|
5
|
+
before do
|
6
|
+
@time = DateTime.now
|
7
|
+
@index = Dynamoid::Indexes::Index.new(User, [:password, :name], :range_key => :created_at)
|
8
|
+
end
|
9
|
+
|
10
|
+
it 'reorders keys alphabetically' do
|
11
|
+
@index.sort([:password, :name, :created_at]).should == [:created_at, :name, :password]
|
12
|
+
end
|
13
|
+
|
14
|
+
it 'assigns itself hash keys' do
|
15
|
+
@index.hash_keys.should == [:name, :password]
|
16
|
+
end
|
17
|
+
|
18
|
+
it 'assigns itself range keys' do
|
19
|
+
@index.range_keys.should == [:created_at]
|
20
|
+
end
|
21
|
+
|
22
|
+
it 'reorders its name automatically' do
|
23
|
+
@index.name.should == [:created_at, :name, :password]
|
24
|
+
end
|
25
|
+
|
26
|
+
it 'determines its own table name' do
|
27
|
+
@index.table_name.should == 'dynamoid_tests_index_user_created_ats_and_names_and_passwords'
|
28
|
+
end
|
29
|
+
|
30
|
+
it 'raises an error if a field does not exist' do
|
31
|
+
lambda {@index = Dynamoid::Indexes::Index.new(User, [:password, :text])}.should raise_error(Dynamoid::Errors::InvalidField)
|
32
|
+
end
|
33
|
+
|
34
|
+
it 'returns values for indexes' do
|
35
|
+
@index.values(:name => 'Josh', :password => 'test123', :created_at => @time).should == {:hash_value => 'Josh.test123', :range_value => @time.to_f}
|
36
|
+
end
|
37
|
+
|
38
|
+
it 'ignores values for fields that do not exist' do
|
39
|
+
@index.values(:name => 'Josh', :password => 'test123', :created_at => @time, :email => 'josh@joshsymonds.com').should == {:hash_value => 'Josh.test123', :range_value => @time.to_f}
|
40
|
+
end
|
41
|
+
|
42
|
+
it 'substitutes a blank string for a hash value that does not exist' do
|
43
|
+
@index.values(:name => 'Josh', :created_at => @time).should == {:hash_value => 'Josh.', :range_value => @time.to_f}
|
44
|
+
end
|
45
|
+
|
46
|
+
it 'substitutes a blank string if both hash values do not exist' do
|
47
|
+
@index.values(:created_at => @time).should == {:hash_value => '.', :range_value => @time.to_f}
|
48
|
+
end
|
49
|
+
|
50
|
+
it 'accepts values from an object instead of a hash' do
|
51
|
+
@user = User.new(:name => 'Josh', :password => 'test123', :created_at => @time)
|
52
|
+
|
53
|
+
@index.values(@user).should == {:hash_value => 'Josh.test123', :range_value => @time.to_f}
|
54
|
+
end
|
55
|
+
|
56
|
+
it 'accepts values from an object and returns changed values' do
|
57
|
+
@user = User.new(:name => 'Josh', :password => 'test123', :created_at => @time)
|
58
|
+
@user.name = 'Justin'
|
59
|
+
|
60
|
+
@index.values(@user).should == {:hash_value => 'Justin.test123', :range_value => @time.to_f}
|
61
|
+
end
|
62
|
+
|
63
|
+
it 'saves an object to the index it is associated with' do
|
64
|
+
@index = Dynamoid::Indexes::Index.new(User, :name)
|
65
|
+
@user = User.new(:name => 'Josh', :password => 'test123', :created_at => @time, :id => 'test123')
|
66
|
+
|
67
|
+
@index.save(@user)
|
68
|
+
|
69
|
+
Dynamoid::Adapter.read("dynamoid_tests_index_user_names", 'Josh')[:ids].should == Set['test123']
|
70
|
+
end
|
71
|
+
|
72
|
+
it 'saves an object to the index it is associated with with a range' do
|
73
|
+
@index = Dynamoid::Indexes::Index.new(User, :name, :range_key => :last_logged_in_at)
|
74
|
+
@user = User.create(:name => 'Josh', :last_logged_in_at => @time)
|
75
|
+
|
76
|
+
@index.save(@user)
|
77
|
+
|
78
|
+
Dynamoid::Adapter.read("dynamoid_tests_index_user_last_logged_in_ats_and_names", 'Josh', :range_key => @time.to_f)[:ids].should == Set[@user.id]
|
79
|
+
end
|
80
|
+
|
81
|
+
it 'deletes an object from the index it is associated with' do
|
82
|
+
@index = Dynamoid::Indexes::Index.new(User, :name)
|
83
|
+
@user = User.create(:name => 'Josh', :password => 'test123', :last_logged_in_at => @time, :id => 'test123')
|
84
|
+
|
85
|
+
@index.save(@user)
|
86
|
+
@index.delete(@user)
|
87
|
+
|
88
|
+
Dynamoid::Adapter.read("dynamoid_tests_index_user_names", 'Josh')[:ids].should be_nil
|
89
|
+
end
|
90
|
+
|
91
|
+
it 'updates an object by removing it from its previous index and adding it to its new one' do
|
92
|
+
@index = Dynamoid::Indexes::Index.new(User, :name)
|
93
|
+
@user = User.create(:name => 'Josh', :password => 'test123', :last_logged_in_at => @time, :id => 'test123')
|
94
|
+
|
95
|
+
Dynamoid::Adapter.read("dynamoid_tests_index_user_names", 'Josh')[:ids].should == Set['test123']
|
96
|
+
Dynamoid::Adapter.read("dynamoid_tests_index_user_names", 'Justin').should be_nil
|
97
|
+
|
98
|
+
@user.update_attributes(:name => 'Justin')
|
99
|
+
|
100
|
+
Dynamoid::Adapter.read("dynamoid_tests_index_user_names", 'Josh')[:ids].should be_nil
|
101
|
+
Dynamoid::Adapter.read("dynamoid_tests_index_user_names", 'Justin')[:ids].should == Set['test123']
|
102
|
+
end
|
103
|
+
|
104
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
|
2
|
+
|
3
|
+
describe "Dynamoid::Indexes" do
|
4
|
+
|
5
|
+
it 'adds indexes to the index array' do
|
6
|
+
User.indexes.keys.should =~ [[:created_at], [:created_at, :name], [:email], [:email, :name], [:last_logged_in_at, :name], [:name]]
|
7
|
+
end
|
8
|
+
|
9
|
+
it 'saves indexes to their tables' do
|
10
|
+
@user = User.new(:name => 'Josh')
|
11
|
+
|
12
|
+
User.indexes.each {|k, v| v.expects(:save).with(@user).once.returns(true)}
|
13
|
+
|
14
|
+
@user.save
|
15
|
+
end
|
16
|
+
|
17
|
+
it 'deletes indexes when the object is destroyed' do
|
18
|
+
@user = User.create(:name => 'Josh')
|
19
|
+
|
20
|
+
User.indexes.each {|k, v| v.expects(:delete).with(@user).once.returns(true)}
|
21
|
+
|
22
|
+
@user.destroy
|
23
|
+
end
|
24
|
+
|
25
|
+
end
|
@@ -0,0 +1,176 @@
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
|
2
|
+
|
3
|
+
describe "Dynamoid::Persistence" do
|
4
|
+
|
5
|
+
before do
|
6
|
+
Random.stubs(:rand).with(Dynamoid::Config.partition_size).returns(0)
|
7
|
+
@address = Address.new
|
8
|
+
end
|
9
|
+
|
10
|
+
context 'without AWS keys' do
|
11
|
+
unless ENV['ACCESS_KEY'] && ENV['SECRET_KEY']
|
12
|
+
before do
|
13
|
+
Dynamoid::Adapter.delete_table(Address.table_name) if Dynamoid::Adapter.list_tables.include?(Address.table_name)
|
14
|
+
end
|
15
|
+
|
16
|
+
it 'creates a table' do
|
17
|
+
Address.create_table(:table_name => Address.table_name)
|
18
|
+
|
19
|
+
Dynamoid::Adapter.list_tables.should include 'dynamoid_tests_addresses'
|
20
|
+
end
|
21
|
+
|
22
|
+
it 'checks if a table already exists' do
|
23
|
+
Address.create_table(:table_name => Address.table_name)
|
24
|
+
|
25
|
+
Address.table_exists?(Address.table_name).should be_true
|
26
|
+
Address.table_exists?('crazytable').should be_false
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
it 'assigns itself an id on save' do
|
32
|
+
@address.save
|
33
|
+
|
34
|
+
Dynamoid::Adapter.read("dynamoid_tests_addresses", @address.id)[:id].should == @address.id
|
35
|
+
end
|
36
|
+
|
37
|
+
it 'assigns itself an id on save only if it does not have one' do
|
38
|
+
@address.id = 'test123'
|
39
|
+
@address.save
|
40
|
+
|
41
|
+
Dynamoid::Adapter.read("dynamoid_tests_addresses", 'test123').should_not be_empty
|
42
|
+
end
|
43
|
+
|
44
|
+
it 'has a table name' do
|
45
|
+
Address.table_name.should == 'dynamoid_tests_addresses'
|
46
|
+
end
|
47
|
+
|
48
|
+
it 'saves indexes along with itself' do
|
49
|
+
@user = User.new(:name => 'Josh')
|
50
|
+
|
51
|
+
@user.expects(:save_indexes).once.returns(true)
|
52
|
+
@user.save
|
53
|
+
end
|
54
|
+
|
55
|
+
it 'deletes an item completely' do
|
56
|
+
@user = User.create(:name => 'Josh')
|
57
|
+
@user.destroy
|
58
|
+
|
59
|
+
Dynamoid::Adapter.read("dynamoid_tests_users", @user.id).should be_nil
|
60
|
+
end
|
61
|
+
|
62
|
+
it 'keeps string attributes as strings' do
|
63
|
+
@user = User.new(:name => 'Josh')
|
64
|
+
@user.send(:dump)[:name].should == 'Josh'
|
65
|
+
end
|
66
|
+
|
67
|
+
it 'dumps datetime attributes' do
|
68
|
+
@user = User.create(:name => 'Josh')
|
69
|
+
@user.send(:dump)[:name].should == 'Josh'
|
70
|
+
end
|
71
|
+
|
72
|
+
it 'dumps integer attributes' do
|
73
|
+
@subscription = Subscription.create(:length => 10)
|
74
|
+
@subscription.send(:dump)[:length].should == 10
|
75
|
+
end
|
76
|
+
|
77
|
+
it 'dumps set attributes' do
|
78
|
+
@subscription = Subscription.create(:length => 10)
|
79
|
+
@magazine = @subscription.magazine.create
|
80
|
+
|
81
|
+
@subscription.send(:dump)[:magazine_ids].should == Set[@magazine.id]
|
82
|
+
end
|
83
|
+
|
84
|
+
it 'handles nil attributes properly' do
|
85
|
+
Address.undump(nil).should be_a(Hash)
|
86
|
+
end
|
87
|
+
|
88
|
+
it 'dumps and undump a serialized field' do
|
89
|
+
@address.options = (hash = {:x => [1, 2], "foobar" => 3.14})
|
90
|
+
Address.undump(@address.send(:dump))[:options].should == hash
|
91
|
+
end
|
92
|
+
|
93
|
+
it 'loads a hash into a serialized field' do
|
94
|
+
hash = {foo: :bar}
|
95
|
+
Address.new(options: hash).options.should == hash
|
96
|
+
end
|
97
|
+
|
98
|
+
it 'loads attributes from a hash' do
|
99
|
+
@time = DateTime.now
|
100
|
+
@hash = {:name => 'Josh', :created_at => @time.to_f}
|
101
|
+
|
102
|
+
User.undump(@hash)[:name].should == 'Josh'
|
103
|
+
User.undump(@hash)[:created_at].to_f == @time.to_f
|
104
|
+
end
|
105
|
+
|
106
|
+
it 'runs the before_create callback only once' do
|
107
|
+
CamelCase.any_instance.expects(:doing_before_create).once.returns(true)
|
108
|
+
|
109
|
+
CamelCase.create
|
110
|
+
end
|
111
|
+
|
112
|
+
it 'runs after save callbacks when doing #create' do
|
113
|
+
CamelCase.any_instance.expects(:doing_after_create).once.returns(true)
|
114
|
+
|
115
|
+
CamelCase.create
|
116
|
+
end
|
117
|
+
|
118
|
+
it 'runs after save callbacks when doing #save' do
|
119
|
+
CamelCase.any_instance.expects(:doing_after_create).once.returns(true)
|
120
|
+
|
121
|
+
CamelCase.new.save
|
122
|
+
end
|
123
|
+
|
124
|
+
it 'works with a HashWithIndifferentAccess' do
|
125
|
+
hash = ActiveSupport::HashWithIndifferentAccess.new("city" => "Atlanta")
|
126
|
+
|
127
|
+
lambda {Address.create(hash)}.should_not raise_error
|
128
|
+
end
|
129
|
+
|
130
|
+
context 'update' do
|
131
|
+
|
132
|
+
before :each do
|
133
|
+
@tweet = Tweet.create(:tweet_id => 1, :group => 'abc', :count => 5, :tags => ['db', 'sql'], :user_name => 'john')
|
134
|
+
end
|
135
|
+
|
136
|
+
it 'support add/delete operation on a field' do
|
137
|
+
@tweet.update do |t|
|
138
|
+
t.add(:count => 3)
|
139
|
+
t.delete(:tags => ['db'])
|
140
|
+
end
|
141
|
+
|
142
|
+
@tweet.count.should eq(8)
|
143
|
+
@tweet.tags.to_a.should eq(['sql'])
|
144
|
+
end
|
145
|
+
|
146
|
+
it 'checks the conditions on update' do
|
147
|
+
@tweet.update(:if => { :count => 5 }) do |t|
|
148
|
+
t.add(:count => 3)
|
149
|
+
end.should be_true
|
150
|
+
|
151
|
+
@tweet.count.should eq(8)
|
152
|
+
|
153
|
+
@tweet.update(:if => { :count => 5 }) do |t|
|
154
|
+
t.add(:count => 3)
|
155
|
+
end.should be_false
|
156
|
+
|
157
|
+
@tweet.count.should eq(8)
|
158
|
+
|
159
|
+
expect {
|
160
|
+
@tweet.update!(:if => { :count => 5 }) do |t|
|
161
|
+
t.add(:count => 3)
|
162
|
+
end
|
163
|
+
}.to raise_error(Dynamoid::Errors::ConditionalCheckFailedException)
|
164
|
+
end
|
165
|
+
|
166
|
+
end
|
167
|
+
|
168
|
+
context 'delete' do
|
169
|
+
it 'deletes model with datetime range key' do
|
170
|
+
lambda {
|
171
|
+
msg = Message.create!(:message_id => 1, :time => DateTime.now, :text => "Hell yeah")
|
172
|
+
msg.destroy
|
173
|
+
}.should_not raise_error
|
174
|
+
end
|
175
|
+
end
|
176
|
+
end
|