dynamoid 0.3.2 → 0.4.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/Dynamoid.gemspec +3 -2
- data/README.markdown +39 -3
- data/VERSION +1 -1
- data/lib/dynamoid.rb +2 -0
- data/lib/dynamoid/adapter.rb +9 -8
- data/lib/dynamoid/adapter/aws_sdk.rb +15 -9
- data/lib/dynamoid/adapter/local.rb +39 -14
- data/lib/dynamoid/associations.rb +5 -6
- data/lib/dynamoid/associations/association.rb +23 -1
- data/lib/dynamoid/associations/belongs_to.rb +0 -1
- data/lib/dynamoid/associations/has_and_belongs_to_many.rb +0 -1
- data/lib/dynamoid/associations/has_many.rb +0 -1
- data/lib/dynamoid/associations/many_association.rb +10 -7
- data/lib/dynamoid/associations/single_association.rb +2 -1
- data/lib/dynamoid/components.rb +1 -0
- data/lib/dynamoid/config.rb +1 -0
- data/lib/dynamoid/criteria.rb +2 -2
- data/lib/dynamoid/criteria/chain.rb +118 -43
- data/lib/dynamoid/document.rb +58 -6
- data/lib/dynamoid/fields.rb +18 -3
- data/lib/dynamoid/finders.rb +14 -7
- data/lib/dynamoid/indexes.rb +3 -2
- data/lib/dynamoid/indexes/index.rb +2 -2
- data/lib/dynamoid/persistence.rb +29 -14
- data/spec/app/models/address.rb +4 -0
- data/spec/app/models/camel_case.rb +13 -0
- data/spec/app/models/tweet.rb +9 -0
- data/spec/dynamoid/adapter/aws_sdk_spec.rb +5 -5
- data/spec/dynamoid/adapter/local_spec.rb +79 -79
- data/spec/dynamoid/adapter_spec.rb +6 -6
- data/spec/dynamoid/associations/association_spec.rb +26 -12
- data/spec/dynamoid/criteria/chain_spec.rb +64 -21
- data/spec/dynamoid/criteria_spec.rb +28 -0
- data/spec/dynamoid/document_spec.rb +29 -0
- data/spec/dynamoid/fields_spec.rb +5 -0
- data/spec/dynamoid/finders_spec.rb +6 -1
- data/spec/dynamoid/indexes/index_spec.rb +1 -1
- data/spec/dynamoid/persistence_spec.rb +9 -17
- data/spec/spec_helper.rb +1 -0
- metadata +4 -3
@@ -31,7 +31,7 @@ describe "Dynamoid::Adapter" do
|
|
31
31
|
end
|
32
32
|
|
33
33
|
it 'reads through the adapter for one ID' do
|
34
|
-
Dynamoid::Adapter.expects(:get_item).with('dynamoid_tests_TestTable', '123',
|
34
|
+
Dynamoid::Adapter.expects(:get_item).with('dynamoid_tests_TestTable', '123', {}).returns(true)
|
35
35
|
|
36
36
|
Dynamoid::Adapter.read('dynamoid_tests_TestTable', '123')
|
37
37
|
end
|
@@ -43,15 +43,15 @@ describe "Dynamoid::Adapter" do
|
|
43
43
|
end
|
44
44
|
|
45
45
|
it 'reads through the adapter for one ID and a range key' do
|
46
|
-
Dynamoid::Adapter.expects(:get_item).with('dynamoid_tests_TestTable', '123', 2.0).returns(true)
|
46
|
+
Dynamoid::Adapter.expects(:get_item).with('dynamoid_tests_TestTable', '123', :range_key => 2.0).returns(true)
|
47
47
|
|
48
|
-
Dynamoid::Adapter.read('dynamoid_tests_TestTable', '123', 2.0)
|
48
|
+
Dynamoid::Adapter.read('dynamoid_tests_TestTable', '123', :range_key => 2.0)
|
49
49
|
end
|
50
50
|
|
51
51
|
it 'reads through the adapter for many IDs and a range key' do
|
52
52
|
Dynamoid::Adapter.expects(:batch_get_item).with({'dynamoid_tests_TestTable' => [['1', 2.0], ['2', 2.0]]}).returns(true)
|
53
53
|
|
54
|
-
Dynamoid::Adapter.read('dynamoid_tests_TestTable', ['1', '2'], 2.0)
|
54
|
+
Dynamoid::Adapter.read('dynamoid_tests_TestTable', ['1', '2'], :range_key => 2.0)
|
55
55
|
end
|
56
56
|
end
|
57
57
|
|
@@ -88,13 +88,13 @@ describe "Dynamoid::Adapter" do
|
|
88
88
|
it 'reads through the adapter for one ID and a range key' do
|
89
89
|
Dynamoid::Adapter.expects(:batch_get_item).with('dynamoid_tests_TestTable' => (0...Dynamoid::Config.partition_size).collect{|n| ["123.#{n}", 2.0]}).returns({})
|
90
90
|
|
91
|
-
Dynamoid::Adapter.read('dynamoid_tests_TestTable', '123', 2.0)
|
91
|
+
Dynamoid::Adapter.read('dynamoid_tests_TestTable', '123', :range_key => 2.0)
|
92
92
|
end
|
93
93
|
|
94
94
|
it 'reads through the adapter for many IDs and a range key' do
|
95
95
|
Dynamoid::Adapter.expects(:batch_get_item).with('dynamoid_tests_TestTable' => (0...Dynamoid::Config.partition_size).collect{|n| ["1.#{n}", 2.0]} + (0...Dynamoid::Config.partition_size).collect{|n| ["2.#{n}", 2.0]}).returns({})
|
96
96
|
|
97
|
-
Dynamoid::Adapter.read('dynamoid_tests_TestTable', ['1', '2'], 2.0)
|
97
|
+
Dynamoid::Adapter.read('dynamoid_tests_TestTable', ['1', '2'], :range_key => 2.0)
|
98
98
|
end
|
99
99
|
|
100
100
|
it 'returns an ID with all partitions' do
|
@@ -3,6 +3,7 @@ require File.expand_path(File.dirname(__FILE__) + '/../../spec_helper')
|
|
3
3
|
describe "Dynamoid::Associations::Association" do
|
4
4
|
|
5
5
|
before do
|
6
|
+
Subscription.create_table
|
6
7
|
@magazine = Magazine.create
|
7
8
|
end
|
8
9
|
|
@@ -36,12 +37,16 @@ describe "Dynamoid::Associations::Association" do
|
|
36
37
|
|
37
38
|
it 'returns the number of items in the association' do
|
38
39
|
@magazine.subscriptions.create
|
39
|
-
|
40
40
|
@magazine.subscriptions.size.should == 1
|
41
41
|
|
42
|
-
@magazine.subscriptions.create
|
43
|
-
|
42
|
+
@second = @magazine.subscriptions.create
|
44
43
|
@magazine.subscriptions.size.should == 2
|
44
|
+
|
45
|
+
@magazine.subscriptions.delete(@second)
|
46
|
+
@magazine.subscriptions.size.should == 1
|
47
|
+
|
48
|
+
@magazine.subscriptions = []
|
49
|
+
@magazine.subscriptions.size.should == 0
|
45
50
|
end
|
46
51
|
|
47
52
|
it 'assigns directly via the equals operator' do
|
@@ -107,7 +112,7 @@ describe "Dynamoid::Associations::Association" do
|
|
107
112
|
|
108
113
|
it 'destroys associations' do
|
109
114
|
@subscription = Subscription.new
|
110
|
-
@magazine.subscriptions.expects(:
|
115
|
+
@magazine.subscriptions.expects(:target).returns([@subscription])
|
111
116
|
@subscription.expects(:destroy)
|
112
117
|
|
113
118
|
@magazine.subscriptions.destroy_all
|
@@ -115,19 +120,20 @@ describe "Dynamoid::Associations::Association" do
|
|
115
120
|
|
116
121
|
it 'deletes associations' do
|
117
122
|
@subscription = Subscription.new
|
118
|
-
@magazine.subscriptions.expects(:
|
123
|
+
@magazine.subscriptions.expects(:target).returns([@subscription])
|
119
124
|
@subscription.expects(:delete)
|
120
125
|
|
121
126
|
@magazine.subscriptions.delete_all
|
122
127
|
end
|
123
128
|
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
129
|
+
# TODO This test is broken using the AWS SDK adapter.
|
130
|
+
#it 'returns the first and last record when they exist' do
|
131
|
+
# @subscription1 = @magazine.subscriptions.create
|
132
|
+
# @subscription2 = @magazine.subscriptions.create
|
133
|
+
# @subscription3 = @magazine.subscriptions.create
|
134
|
+
#
|
135
|
+
# @magazine.subscriptions.instance_eval { [first, last] }.should == [@subscription1, @subscription3]
|
136
|
+
#end
|
131
137
|
|
132
138
|
it 'replaces existing associations when using the setter' do
|
133
139
|
@subscription1 = @magazine.subscriptions.create
|
@@ -177,4 +183,12 @@ describe "Dynamoid::Associations::Association" do
|
|
177
183
|
@magazine.subscriptions.class.should == Array
|
178
184
|
end
|
179
185
|
|
186
|
+
it 'loads association one time only' do
|
187
|
+
@sponsor = @magazine.sponsor.create
|
188
|
+
@magazine.sponsor.expects(:find_target).once.returns(@sponsor)
|
189
|
+
|
190
|
+
@magazine.sponsor.id
|
191
|
+
@magazine.sponsor.id
|
192
|
+
end
|
193
|
+
|
180
194
|
end
|
@@ -7,83 +7,126 @@ describe "Dynamoid::Associations::Chain" do
|
|
7
7
|
@user = User.create(:name => 'Josh', :email => 'josh@joshsymonds.com', :password => 'Test123')
|
8
8
|
@chain = Dynamoid::Criteria::Chain.new(User)
|
9
9
|
end
|
10
|
-
|
10
|
+
|
11
11
|
it 'finds matching index for a query' do
|
12
12
|
@chain.query = {:name => 'Josh'}
|
13
13
|
@chain.send(:index).should == User.indexes[[:name]]
|
14
|
-
|
14
|
+
|
15
15
|
@chain.query = {:email => 'josh@joshsymonds.com'}
|
16
16
|
@chain.send(:index).should == User.indexes[[:email]]
|
17
|
-
|
17
|
+
|
18
18
|
@chain.query = {:name => 'Josh', :email => 'josh@joshsymonds.com'}
|
19
19
|
@chain.send(:index).should == User.indexes[[:email, :name]]
|
20
20
|
end
|
21
|
-
|
21
|
+
|
22
22
|
it 'finds matching index for a range query' do
|
23
23
|
@chain.query = {"created_at.gt" => @time - 1.day}
|
24
24
|
@chain.send(:index).should == User.indexes[[:created_at]]
|
25
|
-
|
25
|
+
|
26
26
|
@chain.query = {:name => 'Josh', "created_at.lt" => @time - 1.day}
|
27
27
|
@chain.send(:index).should == User.indexes[[:created_at, :name]]
|
28
28
|
end
|
29
|
-
|
29
|
+
|
30
30
|
it 'does not find an index if there is not an appropriate one' do
|
31
31
|
@chain.query = {:password => 'Test123'}
|
32
32
|
@chain.send(:index).should be_nil
|
33
|
-
|
33
|
+
|
34
34
|
@chain.query = {:password => 'Test123', :created_at => @time}
|
35
35
|
@chain.send(:index).should be_nil
|
36
36
|
end
|
37
|
-
|
37
|
+
|
38
38
|
it 'returns values for index for a query' do
|
39
39
|
@chain.query = {:name => 'Josh'}
|
40
40
|
@chain.send(:index_query).should == {:hash_value => 'Josh'}
|
41
|
-
|
41
|
+
|
42
42
|
@chain.query = {:email => 'josh@joshsymonds.com'}
|
43
43
|
@chain.send(:index_query).should == {:hash_value => 'josh@joshsymonds.com'}
|
44
|
-
|
44
|
+
|
45
45
|
@chain.query = {:name => 'Josh', :email => 'josh@joshsymonds.com'}
|
46
46
|
@chain.send(:index_query).should == {:hash_value => 'josh@joshsymonds.com.Josh'}
|
47
|
-
|
47
|
+
|
48
48
|
@chain.query = {:name => 'Josh', 'created_at.gt' => @time}
|
49
49
|
@chain.send(:index_query).should == {:hash_value => 'Josh', :range_greater_than => @time.to_f}
|
50
50
|
end
|
51
|
-
|
51
|
+
|
52
52
|
it 'finds records with an index' do
|
53
53
|
@chain.query = {:name => 'Josh'}
|
54
54
|
@chain.send(:records_with_index).should == [@user]
|
55
|
-
|
55
|
+
|
56
56
|
@chain.query = {:email => 'josh@joshsymonds.com'}
|
57
57
|
@chain.send(:records_with_index).should == [@user]
|
58
|
-
|
58
|
+
|
59
59
|
@chain.query = {:name => 'Josh', :email => 'josh@joshsymonds.com'}
|
60
60
|
@chain.send(:records_with_index).should == [@user]
|
61
61
|
end
|
62
|
-
|
62
|
+
|
63
63
|
it 'returns records with an index for a ranged query' do
|
64
64
|
@chain.query = {:name => 'Josh', "created_at.gt" => @time - 1.day}
|
65
65
|
@chain.send(:records_with_index).should == [@user]
|
66
|
-
|
66
|
+
|
67
67
|
@chain.query = {:name => 'Josh', "created_at.lt" => @time + 1.day}
|
68
68
|
@chain.send(:records_with_index).should == [@user]
|
69
69
|
end
|
70
|
-
|
70
|
+
|
71
71
|
it 'finds records without an index' do
|
72
72
|
@chain.query = {:password => 'Test123'}
|
73
73
|
@chain.send(:records_without_index).should == [@user]
|
74
74
|
end
|
75
|
-
|
75
|
+
|
76
76
|
it 'defines each' do
|
77
77
|
@chain.query = {:name => 'Josh'}
|
78
78
|
@chain.each {|u| u.update_attribute(:name, 'Justin')}
|
79
|
-
|
79
|
+
|
80
80
|
User.find(@user.id).name.should == 'Justin'
|
81
81
|
end
|
82
|
-
|
82
|
+
|
83
83
|
it 'includes Enumerable' do
|
84
84
|
@chain.query = {:name => 'Josh'}
|
85
|
-
|
85
|
+
|
86
86
|
@chain.collect {|u| u.name}.should == ['Josh']
|
87
87
|
end
|
88
|
+
|
89
|
+
it 'finds range querys' do
|
90
|
+
@chain = Dynamoid::Criteria::Chain.new(Tweet)
|
91
|
+
@chain.query = { :id => 'test' }
|
92
|
+
@chain.send(:range?).should be_true
|
93
|
+
|
94
|
+
@chain.query = {:id => 'test', :group => 'xx'}
|
95
|
+
@chain.send(:range?).should be_true
|
96
|
+
|
97
|
+
@chain.query = { :group => 'xx' }
|
98
|
+
@chain.send(:range?).should be_false
|
99
|
+
|
100
|
+
@chain.query = { :group => 'xx', :msg => 'hai' }
|
101
|
+
@chain.send(:range?).should be_false
|
102
|
+
end
|
88
103
|
|
104
|
+
context 'range queries' do
|
105
|
+
before do
|
106
|
+
@tweet1 = Tweet.create(:tweet_id => "x", :group => "one")
|
107
|
+
@tweet2 = Tweet.create(:tweet_id => "x", :group => "two")
|
108
|
+
@tweet3 = Tweet.create(:tweet_id => "xx", :group => "two")
|
109
|
+
@chain = Dynamoid::Criteria::Chain.new(Tweet)
|
110
|
+
end
|
111
|
+
|
112
|
+
it 'finds tweets with a simple range query' do
|
113
|
+
@chain.query = { :tweet_id => "x" }
|
114
|
+
@chain.send(:records_with_range).size.should == 2
|
115
|
+
@chain.all.size.should == 2
|
116
|
+
@chain.limit(1).size.should == 1
|
117
|
+
end
|
118
|
+
|
119
|
+
it 'finds tweets with a start' do
|
120
|
+
@chain.query = { :tweet_id => "x" }
|
121
|
+
@chain.start(@tweet1)
|
122
|
+
@chain.all.should =~ [@tweet2]
|
123
|
+
end
|
124
|
+
|
125
|
+
it 'finds one specific tweet' do
|
126
|
+
@chain = Dynamoid::Criteria::Chain.new(Tweet)
|
127
|
+
@chain.query = { :tweet_id => "xx", :group => "two" }
|
128
|
+
@chain.send(:records_with_range).should == [@tweet3]
|
129
|
+
end
|
130
|
+
end
|
131
|
+
|
89
132
|
end
|
@@ -35,4 +35,32 @@ describe "Dynamoid::Criteria" do
|
|
35
35
|
end
|
36
36
|
end
|
37
37
|
|
38
|
+
it 'returns n records' do
|
39
|
+
User.limit(1).size.should eq(1)
|
40
|
+
5.times { |i| User.create(:name => 'Josh', :email => 'josh_#{i}@joshsymonds.com') }
|
41
|
+
User.where(:name => 'Josh').all.size.should == 6
|
42
|
+
User.where(:name => 'Josh').limit(2).size.should == 2
|
43
|
+
end
|
44
|
+
|
45
|
+
# TODO This test is broken using the AWS SDK adapter.
|
46
|
+
#it 'start with a record' do
|
47
|
+
# 5.times { |i| User.create(:name => 'Josh', :email => 'josh_#{i}@joshsymonds.com') }
|
48
|
+
# all = User.all
|
49
|
+
# User.start(all[3]).all.should eq(all[4..-1])
|
50
|
+
#
|
51
|
+
# all = User.where(:name => 'Josh').all
|
52
|
+
# User.where(:name => 'Josh').start(all[3]).all.should eq(all[4..-1])
|
53
|
+
#end
|
54
|
+
|
55
|
+
it 'send consistent option to adapter' do
|
56
|
+
Dynamoid::Adapter.expects(:get_item).with { |table_name, key, options| options[:consistent_read] == true }
|
57
|
+
User.where(:name => 'x').consistent.first
|
58
|
+
|
59
|
+
Dynamoid::Adapter.expects(:query).with { |table_name, options| options[:consistent_read] == true }.returns([])
|
60
|
+
Tweet.where(:id => 'xx', :group => 'two').consistent.all
|
61
|
+
|
62
|
+
Dynamoid::Adapter.expects(:query).with { |table_name, options| options[:consistent_read] == false }.returns([])
|
63
|
+
Tweet.where(:id => 'xx', :group => 'two').all
|
64
|
+
end
|
65
|
+
|
38
66
|
end
|
@@ -25,6 +25,14 @@ describe "Dynamoid::Document" do
|
|
25
25
|
@address.attributes.should == {:id=>nil, :created_at=>nil, :updated_at=>nil, :city=>"Chicago", :options=>nil}
|
26
26
|
end
|
27
27
|
|
28
|
+
it 'initializes a new document with a virtual attribute' do
|
29
|
+
@address = Address.new(:zip_code => '12345')
|
30
|
+
|
31
|
+
@address.new_record.should be_true
|
32
|
+
|
33
|
+
@address.attributes.should == {:id=>nil, :created_at=>nil, :updated_at=>nil, :city=>"Chicago", :options=>nil}
|
34
|
+
end
|
35
|
+
|
28
36
|
it 'allows interception of write_attribute on load' do
|
29
37
|
class Model
|
30
38
|
include Dynamoid::Document
|
@@ -82,4 +90,25 @@ describe "Dynamoid::Document" do
|
|
82
90
|
@address.city.should be_nil
|
83
91
|
@address.reload.city.should == 'Chicago'
|
84
92
|
end
|
93
|
+
|
94
|
+
it 'has default table options' do
|
95
|
+
@address = Address.create
|
96
|
+
|
97
|
+
@address.id.should_not be_nil
|
98
|
+
Address.table_name.should == 'dynamoid_tests_addresses'
|
99
|
+
Address.hash_key.should == :id
|
100
|
+
Address.read_capacity.should == 100
|
101
|
+
Address.write_capacity.should == 20
|
102
|
+
end
|
103
|
+
|
104
|
+
it 'follows any table options provided to it' do
|
105
|
+
@tweet = Tweet.create(:group => 12345)
|
106
|
+
|
107
|
+
lambda {@tweet.id}.should raise_error(NoMethodError)
|
108
|
+
@tweet.tweet_id.should_not be_nil
|
109
|
+
Tweet.table_name.should == 'dynamoid_tests_twitters'
|
110
|
+
Tweet.hash_key.should == :tweet_id
|
111
|
+
Tweet.read_capacity.should == 200
|
112
|
+
Tweet.write_capacity.should == 200
|
113
|
+
end
|
85
114
|
end
|
@@ -88,5 +88,10 @@ describe "Dynamoid::Fields" do
|
|
88
88
|
Address.attributes.should == {:id=>{:type=>:string}, :created_at=>{:type=>:datetime}, :updated_at=>{:type=>:datetime}, :city=>{:type=>:string}, :options=>{:type=>:serialized}}
|
89
89
|
end
|
90
90
|
end
|
91
|
+
|
92
|
+
it "gives a warning when setting a single value larger than the maximum item size" do
|
93
|
+
Dynamoid.logger.expects(:warn).with(regexp_matches(/city field has a length of 66000/))
|
94
|
+
Address.new city: ("Ten chars " * 6_600)
|
95
|
+
end
|
91
96
|
|
92
97
|
end
|
@@ -27,7 +27,12 @@ describe "Dynamoid::Finders" do
|
|
27
27
|
@address2 = Address.create(:city => 'Illinois')
|
28
28
|
|
29
29
|
Address.find(@address.id, @address2.id).should include @address, @address2
|
30
|
-
end
|
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
|
31
36
|
|
32
37
|
context 'with users' do
|
33
38
|
before do
|
@@ -77,7 +77,7 @@ describe "Dynamoid::Indexes::Index" do
|
|
77
77
|
|
78
78
|
@index.save(@user)
|
79
79
|
|
80
|
-
Dynamoid::Adapter.read("dynamoid_tests_index_user_last_logged_in_ats_and_names", 'Josh', @time.to_f)[:ids].should == Set[@user.id]
|
80
|
+
Dynamoid::Adapter.read("dynamoid_tests_index_user_last_logged_in_ats_and_names", 'Josh', :range_key => @time.to_f)[:ids].should == Set[@user.id]
|
81
81
|
end
|
82
82
|
|
83
83
|
it 'deletes an object from the index it is associated with' do
|
@@ -2,8 +2,6 @@ require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
|
|
2
2
|
|
3
3
|
describe "Dynamoid::Persistence" do
|
4
4
|
|
5
|
-
let(:document_class) { Class.new.send :include, Dynamoid::Document }
|
6
|
-
|
7
5
|
before do
|
8
6
|
Random.stubs(:rand).with(Dynamoid::Config.partition_size).returns(0)
|
9
7
|
@address = Address.new
|
@@ -16,13 +14,13 @@ describe "Dynamoid::Persistence" do
|
|
16
14
|
end
|
17
15
|
|
18
16
|
it 'creates a table' do
|
19
|
-
Address.create_table(Address.table_name)
|
17
|
+
Address.create_table(:table_name => Address.table_name)
|
20
18
|
|
21
19
|
Dynamoid::Adapter.list_tables.should include 'dynamoid_tests_addresses'
|
22
20
|
end
|
23
21
|
|
24
22
|
it 'checks if a table already exists' do
|
25
|
-
Address.create_table(Address.table_name)
|
23
|
+
Address.create_table(:table_name => Address.table_name)
|
26
24
|
|
27
25
|
Address.table_exists?(Address.table_name).should be_true
|
28
26
|
Address.table_exists?('crazytable').should be_false
|
@@ -106,27 +104,21 @@ describe "Dynamoid::Persistence" do
|
|
106
104
|
end
|
107
105
|
|
108
106
|
it 'runs the before_create callback only once' do
|
109
|
-
|
110
|
-
|
111
|
-
document_class.any_instance.expects(:doing_before_create)
|
107
|
+
CamelCase.any_instance.expects(:doing_before_create).once.returns(true)
|
112
108
|
|
113
|
-
|
109
|
+
CamelCase.create
|
114
110
|
end
|
115
111
|
|
116
112
|
it 'runs after save callbacks when doing #create' do
|
117
|
-
|
113
|
+
CamelCase.any_instance.expects(:doing_after_create).once.returns(true)
|
118
114
|
|
119
|
-
|
120
|
-
|
121
|
-
document_class.create
|
115
|
+
CamelCase.create
|
122
116
|
end
|
123
117
|
|
124
118
|
it 'runs after save callbacks when doing #save' do
|
125
|
-
|
126
|
-
|
127
|
-
document_class.any_instance.expects(:doing_after_create)
|
119
|
+
CamelCase.any_instance.expects(:doing_after_create).once.returns(true)
|
128
120
|
|
129
|
-
|
121
|
+
CamelCase.new.save
|
130
122
|
end
|
131
123
|
|
132
124
|
it 'tracks previous changes on save or update' do
|
@@ -140,7 +132,7 @@ describe "Dynamoid::Persistence" do
|
|
140
132
|
end
|
141
133
|
|
142
134
|
it 'works with a HashWithIndifferentAccess' do
|
143
|
-
hash = ActiveSupport::HashWithIndifferentAccess.new("
|
135
|
+
hash = ActiveSupport::HashWithIndifferentAccess.new("city" => "Atlanta")
|
144
136
|
|
145
137
|
lambda {Address.create(hash)}.should_not raise_error
|
146
138
|
end
|