adept_dynamoid 0.5.0.6

Sign up to get free protection for your applications and to get access to all the features.
Files changed (119) hide show
  1. data/.document +5 -0
  2. data/.rspec +1 -0
  3. data/Dynamoid.gemspec +193 -0
  4. data/Gemfile +23 -0
  5. data/Gemfile.lock +86 -0
  6. data/LICENSE.txt +20 -0
  7. data/README.markdown +265 -0
  8. data/Rakefile +62 -0
  9. data/VERSION +1 -0
  10. data/doc/.nojekyll +0 -0
  11. data/doc/Dynamoid.html +312 -0
  12. data/doc/Dynamoid/Adapter.html +1385 -0
  13. data/doc/Dynamoid/Adapter/AwsSdk.html +1585 -0
  14. data/doc/Dynamoid/Adapter/Local.html +1574 -0
  15. data/doc/Dynamoid/Associations.html +131 -0
  16. data/doc/Dynamoid/Associations/Association.html +794 -0
  17. data/doc/Dynamoid/Associations/BelongsTo.html +158 -0
  18. data/doc/Dynamoid/Associations/ClassMethods.html +723 -0
  19. data/doc/Dynamoid/Associations/HasAndBelongsToMany.html +164 -0
  20. data/doc/Dynamoid/Associations/HasMany.html +164 -0
  21. data/doc/Dynamoid/Associations/HasOne.html +158 -0
  22. data/doc/Dynamoid/Associations/ManyAssociation.html +1640 -0
  23. data/doc/Dynamoid/Associations/SingleAssociation.html +598 -0
  24. data/doc/Dynamoid/Components.html +204 -0
  25. data/doc/Dynamoid/Config.html +395 -0
  26. data/doc/Dynamoid/Config/Options.html +609 -0
  27. data/doc/Dynamoid/Criteria.html +131 -0
  28. data/doc/Dynamoid/Criteria/Chain.html +1063 -0
  29. data/doc/Dynamoid/Criteria/ClassMethods.html +98 -0
  30. data/doc/Dynamoid/Document.html +666 -0
  31. data/doc/Dynamoid/Document/ClassMethods.html +937 -0
  32. data/doc/Dynamoid/Errors.html +118 -0
  33. data/doc/Dynamoid/Errors/DocumentNotValid.html +210 -0
  34. data/doc/Dynamoid/Errors/Error.html +130 -0
  35. data/doc/Dynamoid/Errors/InvalidField.html +133 -0
  36. data/doc/Dynamoid/Errors/MissingRangeKey.html +133 -0
  37. data/doc/Dynamoid/Fields.html +669 -0
  38. data/doc/Dynamoid/Fields/ClassMethods.html +309 -0
  39. data/doc/Dynamoid/Finders.html +128 -0
  40. data/doc/Dynamoid/Finders/ClassMethods.html +516 -0
  41. data/doc/Dynamoid/Indexes.html +308 -0
  42. data/doc/Dynamoid/Indexes/ClassMethods.html +353 -0
  43. data/doc/Dynamoid/Indexes/Index.html +1104 -0
  44. data/doc/Dynamoid/Persistence.html +651 -0
  45. data/doc/Dynamoid/Persistence/ClassMethods.html +670 -0
  46. data/doc/Dynamoid/Validations.html +399 -0
  47. data/doc/_index.html +461 -0
  48. data/doc/class_list.html +47 -0
  49. data/doc/css/common.css +1 -0
  50. data/doc/css/full_list.css +55 -0
  51. data/doc/css/style.css +322 -0
  52. data/doc/file.LICENSE.html +66 -0
  53. data/doc/file.README.html +312 -0
  54. data/doc/file_list.html +52 -0
  55. data/doc/frames.html +13 -0
  56. data/doc/index.html +312 -0
  57. data/doc/js/app.js +205 -0
  58. data/doc/js/full_list.js +173 -0
  59. data/doc/js/jquery.js +16 -0
  60. data/doc/method_list.html +1238 -0
  61. data/doc/top-level-namespace.html +105 -0
  62. data/lib/dynamoid.rb +47 -0
  63. data/lib/dynamoid/adapter.rb +177 -0
  64. data/lib/dynamoid/adapter/aws_sdk.rb +223 -0
  65. data/lib/dynamoid/associations.rb +106 -0
  66. data/lib/dynamoid/associations/association.rb +105 -0
  67. data/lib/dynamoid/associations/belongs_to.rb +44 -0
  68. data/lib/dynamoid/associations/has_and_belongs_to_many.rb +40 -0
  69. data/lib/dynamoid/associations/has_many.rb +39 -0
  70. data/lib/dynamoid/associations/has_one.rb +39 -0
  71. data/lib/dynamoid/associations/many_association.rb +191 -0
  72. data/lib/dynamoid/associations/single_association.rb +69 -0
  73. data/lib/dynamoid/components.rb +36 -0
  74. data/lib/dynamoid/config.rb +57 -0
  75. data/lib/dynamoid/config/options.rb +78 -0
  76. data/lib/dynamoid/criteria.rb +29 -0
  77. data/lib/dynamoid/criteria/chain.rb +243 -0
  78. data/lib/dynamoid/dirty.rb +41 -0
  79. data/lib/dynamoid/document.rb +184 -0
  80. data/lib/dynamoid/errors.rb +28 -0
  81. data/lib/dynamoid/fields.rb +130 -0
  82. data/lib/dynamoid/finders.rb +131 -0
  83. data/lib/dynamoid/identity_map.rb +96 -0
  84. data/lib/dynamoid/indexes.rb +69 -0
  85. data/lib/dynamoid/indexes/index.rb +103 -0
  86. data/lib/dynamoid/middleware/identity_map.rb +16 -0
  87. data/lib/dynamoid/persistence.rb +247 -0
  88. data/lib/dynamoid/validations.rb +36 -0
  89. data/spec/app/models/address.rb +10 -0
  90. data/spec/app/models/camel_case.rb +24 -0
  91. data/spec/app/models/magazine.rb +11 -0
  92. data/spec/app/models/message.rb +9 -0
  93. data/spec/app/models/sponsor.rb +8 -0
  94. data/spec/app/models/subscription.rb +12 -0
  95. data/spec/app/models/tweet.rb +12 -0
  96. data/spec/app/models/user.rb +26 -0
  97. data/spec/dynamoid/adapter/aws_sdk_spec.rb +186 -0
  98. data/spec/dynamoid/adapter_spec.rb +117 -0
  99. data/spec/dynamoid/associations/association_spec.rb +194 -0
  100. data/spec/dynamoid/associations/belongs_to_spec.rb +71 -0
  101. data/spec/dynamoid/associations/has_and_belongs_to_many_spec.rb +47 -0
  102. data/spec/dynamoid/associations/has_many_spec.rb +42 -0
  103. data/spec/dynamoid/associations/has_one_spec.rb +45 -0
  104. data/spec/dynamoid/associations_spec.rb +16 -0
  105. data/spec/dynamoid/config_spec.rb +27 -0
  106. data/spec/dynamoid/criteria/chain_spec.rb +140 -0
  107. data/spec/dynamoid/criteria_spec.rb +72 -0
  108. data/spec/dynamoid/dirty_spec.rb +49 -0
  109. data/spec/dynamoid/document_spec.rb +118 -0
  110. data/spec/dynamoid/fields_spec.rb +127 -0
  111. data/spec/dynamoid/finders_spec.rb +135 -0
  112. data/spec/dynamoid/identity_map_spec.rb +45 -0
  113. data/spec/dynamoid/indexes/index_spec.rb +104 -0
  114. data/spec/dynamoid/indexes_spec.rb +25 -0
  115. data/spec/dynamoid/persistence_spec.rb +176 -0
  116. data/spec/dynamoid/validations_spec.rb +36 -0
  117. data/spec/dynamoid_spec.rb +9 -0
  118. data/spec/spec_helper.rb +50 -0
  119. 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