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,140 @@
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 'finds matching index for a range query' do
23
+ @chain.query = {"created_at.gt" => @time - 1.day}
24
+ @chain.send(:index).should == User.indexes[[:created_at]]
25
+
26
+ @chain.query = {:name => 'Josh', "created_at.lt" => @time - 1.day}
27
+ @chain.send(:index).should == User.indexes[[:created_at, :name]]
28
+ end
29
+
30
+ it 'does not find an index if there is not an appropriate one' do
31
+ @chain.query = {:password => 'Test123'}
32
+ @chain.send(:index).should be_nil
33
+
34
+ @chain.query = {:password => 'Test123', :created_at => @time}
35
+ @chain.send(:index).should be_nil
36
+ end
37
+
38
+ it 'returns values for index for a query' do
39
+ @chain.query = {:name => 'Josh'}
40
+ @chain.send(:index_query).should == {:hash_value => 'Josh'}
41
+
42
+ @chain.query = {:email => 'josh@joshsymonds.com'}
43
+ @chain.send(:index_query).should == {:hash_value => 'josh@joshsymonds.com'}
44
+
45
+ @chain.query = {:name => 'Josh', :email => 'josh@joshsymonds.com'}
46
+ @chain.send(:index_query).should == {:hash_value => 'josh@joshsymonds.com.Josh'}
47
+
48
+ @chain.query = {:name => 'Josh', 'created_at.gt' => @time}
49
+ @chain.send(:index_query).should == {:hash_value => 'Josh', :range_greater_than => @time.to_f}
50
+ end
51
+
52
+ it 'finds records with an index' do
53
+ @chain.query = {:name => 'Josh'}
54
+ @chain.send(:records_with_index).should == [@user]
55
+
56
+ @chain.query = {:email => 'josh@joshsymonds.com'}
57
+ @chain.send(:records_with_index).should == [@user]
58
+
59
+ @chain.query = {:name => 'Josh', :email => 'josh@joshsymonds.com'}
60
+ @chain.send(:records_with_index).should == [@user]
61
+ end
62
+
63
+ it 'returns records with an index for a ranged query' do
64
+ @chain.query = {:name => 'Josh', "created_at.gt" => @time - 1.day}
65
+ @chain.send(:records_with_index).should == [@user]
66
+
67
+ @chain.query = {:name => 'Josh', "created_at.lt" => @time + 1.day}
68
+ @chain.send(:records_with_index).should == [@user]
69
+ end
70
+
71
+ it 'finds records without an index' do
72
+ @chain.query = {:password => 'Test123'}
73
+ @chain.send(:records_without_index).should == [@user]
74
+ end
75
+
76
+ it "doesn't crash if it finds a nil id in the index" do
77
+ @chain.query = {:name => 'Josh', "created_at.gt" => @time - 1.day}
78
+ Dynamoid::Adapter.expects(:query).
79
+ with("dynamoid_tests_index_user_created_ats_and_names", kind_of(Hash)).
80
+ returns([{ids: nil}, {ids: Set.new([42])}])
81
+ @chain.send(:ids_from_index).should == Set.new([42])
82
+ end
83
+
84
+ it 'defines each' do
85
+ @chain.query = {:name => 'Josh'}
86
+ @chain.each {|u| u.update_attribute(:name, 'Justin')}
87
+
88
+ User.find(@user.id).name.should == 'Justin'
89
+ end
90
+
91
+ it 'includes Enumerable' do
92
+ @chain.query = {:name => 'Josh'}
93
+
94
+ @chain.collect {|u| u.name}.should == ['Josh']
95
+ end
96
+
97
+ it 'finds range querys' do
98
+ @chain = Dynamoid::Criteria::Chain.new(Tweet)
99
+ @chain.query = { :tweet_id => 'test' }
100
+ @chain.send(:range?).should be_true
101
+
102
+ @chain.query = {:tweet_id => 'test', :group => 'xx'}
103
+ @chain.send(:range?).should be_true
104
+
105
+ @chain.query = { :group => 'xx' }
106
+ @chain.send(:range?).should be_false
107
+
108
+ @chain.query = { :group => 'xx', :msg => 'hai' }
109
+ @chain.send(:range?).should be_false
110
+ end
111
+
112
+ context 'range queries' do
113
+ before do
114
+ @tweet1 = Tweet.create(:tweet_id => "x", :group => "one")
115
+ @tweet2 = Tweet.create(:tweet_id => "x", :group => "two")
116
+ @tweet3 = Tweet.create(:tweet_id => "xx", :group => "two")
117
+ @chain = Dynamoid::Criteria::Chain.new(Tweet)
118
+ end
119
+
120
+ it 'finds tweets with a simple range query' do
121
+ @chain.query = { :tweet_id => "x" }
122
+ @chain.send(:records_with_range).size.should == 2
123
+ @chain.all.size.should == 2
124
+ @chain.limit(1).size.should == 1
125
+ end
126
+
127
+ it 'finds tweets with a start' do
128
+ @chain.query = { :tweet_id => "x" }
129
+ @chain.start(@tweet1)
130
+ @chain.all.should =~ [@tweet2]
131
+ end
132
+
133
+ it 'finds one specific tweet' do
134
+ @chain = Dynamoid::Criteria::Chain.new(Tweet)
135
+ @chain.query = { :tweet_id => "xx", :group => "two" }
136
+ @chain.send(:records_with_range).should == [@tweet3]
137
+ end
138
+ end
139
+
140
+ end
@@ -0,0 +1,72 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
2
+
3
+ describe "Dynamoid::Criteria" do
4
+
5
+ before do
6
+ @user1 = User.create(:name => 'Josh', :email => 'josh@joshsymonds.com')
7
+ @user2 = User.create(:name => 'Justin', :email => 'justin@joshsymonds.com')
8
+ end
9
+
10
+ it 'finds first using where' do
11
+ User.where(:name => 'Josh').first.should == @user1
12
+ end
13
+
14
+ it 'finds all using where' do
15
+ User.where(:name => 'Josh').all.should == [@user1]
16
+ end
17
+
18
+ it 'returns all records' do
19
+ User.all.should =~ [@user1, @user2]
20
+ User.all.first.new_record.should be_false
21
+ end
22
+
23
+ it 'returns empty attributes for where' do
24
+ Magazine.where(:name => 'Josh').all.should == []
25
+ end
26
+
27
+ it 'returns empty attributes for all' do
28
+ Magazine.all.should == []
29
+ end
30
+
31
+ it 'passes each to all members' do
32
+ User.each do |u|
33
+ u.id.should == @user1.id || @user2.id
34
+ u.new_record.should be_false
35
+ end
36
+ end
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(:tweet_id => 'xx', :group => 'two').consistent.all
61
+
62
+ Dynamoid::Adapter.expects(:query).with { |table_name, options| options[:consistent_read] == false }.returns([])
63
+ Tweet.where(:tweet_id => 'xx', :group => 'two').all
64
+ end
65
+
66
+ it 'raises exception when consistent_read is used with scan' do
67
+ expect do
68
+ User.where(:password => 'password').consistent.first
69
+ end.to raise_error(Dynamoid::Errors::InvalidQuery)
70
+ end
71
+
72
+ end
@@ -0,0 +1,49 @@
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 'track changes after saves' do
27
+ tweet = Tweet.new(:tweet_id => "1", :group => 'abc')
28
+ tweet.save!
29
+ tweet.changed?.should be_false
30
+
31
+ tweet.user_name = 'xyz'
32
+ tweet.user_name_changed?.should be_true
33
+ tweet.user_name_was.should be_nil
34
+ tweet.save!
35
+
36
+ tweet.user_name_changed?.should be_false
37
+ tweet.user_name = 'abc'
38
+ tweet.user_name_was.should == 'xyz'
39
+ end
40
+
41
+ it 'clear changes on save' do
42
+ tweet = Tweet.new(:tweet_id => "1", :group => 'abc')
43
+ tweet.group = 'xyz'
44
+ tweet.group_changed?.should be_true
45
+ tweet.save!
46
+ tweet.group_changed?.should be_false
47
+ end
48
+ end
49
+ end
@@ -0,0 +1,118 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
2
+
3
+ describe "Dynamoid::Document" do
4
+
5
+ it 'initializes a new document' do
6
+ @address = Address.new
7
+
8
+ @address.new_record.should be_true
9
+ @address.attributes.should == {:id=>nil, :created_at=>nil, :updated_at=>nil, :city=>nil, :options=>nil}
10
+ end
11
+
12
+ it 'responds to will_change! methods for all fields' do
13
+ @address = Address.new
14
+ @address.should respond_to(:id_will_change!)
15
+ @address.should respond_to(:options_will_change!)
16
+ @address.should respond_to(:created_at_will_change!)
17
+ @address.should respond_to(:updated_at_will_change!)
18
+ end
19
+
20
+ it 'initializes a new document with attributes' do
21
+ @address = Address.new(:city => 'Chicago')
22
+
23
+ @address.new_record.should be_true
24
+
25
+ @address.attributes.should == {:id=>nil, :created_at=>nil, :updated_at=>nil, :city=>"Chicago", :options=>nil}
26
+ end
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
+
36
+ it 'allows interception of write_attribute on load' do
37
+ class Model
38
+ include Dynamoid::Document
39
+ field :city
40
+ def city=(value); self[:city] = value.downcase; end
41
+ end
42
+ Model.new(:city => "Chicago").city.should == "chicago"
43
+ end
44
+
45
+ it 'creates a new document' do
46
+ @address = Address.create(:city => 'Chicago')
47
+
48
+ @address.new_record.should be_false
49
+ @address.id.should_not be_nil
50
+ end
51
+
52
+ it 'knows if a document exists or not' do
53
+ @address = Address.create(:city => 'Chicago')
54
+ Address.exists?(@address.id).should be_true
55
+ Address.exists?("does-not-exist").should be_false
56
+ end
57
+
58
+ it 'tests equivalency with itself' do
59
+ @address = Address.create(:city => 'Chicago')
60
+
61
+ @address.should == @address
62
+ end
63
+
64
+ it 'is not equivalent to another document' do
65
+ @address.should_not == Address.create
66
+ end
67
+
68
+ it 'is not equivalent to another object' do
69
+ @address = Address.create(:city => 'Chicago')
70
+ @address.should_not == "test"
71
+ end
72
+
73
+ it "isn't equal to nil" do
74
+ @address = Address.create(:city => 'Chicago')
75
+ @address.should_not == nil
76
+ end
77
+
78
+ it 'gets errors courtesy of ActiveModel' do
79
+ @address = Address.create(:city => 'Chicago')
80
+
81
+ @address.errors.should be_empty
82
+ @address.errors.full_messages.should be_empty
83
+ end
84
+
85
+ it 'reloads itself and sees persisted changes' do
86
+ @address = Address.create
87
+
88
+ Address.first.update_attributes(:city => 'Chicago')
89
+
90
+ @address.reload.city.should == 'Chicago'
91
+ end
92
+
93
+ it 'reloads document with range key' do
94
+ tweet = Tweet.create(:tweet_id => 'x', :group => 'abc')
95
+ tweet.reload.group.should == 'abc'
96
+ end
97
+
98
+ it 'has default table options' do
99
+ @address = Address.create
100
+
101
+ @address.id.should_not be_nil
102
+ Address.table_name.should == 'dynamoid_tests_addresses'
103
+ Address.hash_key.should == :id
104
+ Address.read_capacity.should == 100
105
+ Address.write_capacity.should == 20
106
+ end
107
+
108
+ it 'follows any table options provided to it' do
109
+ @tweet = Tweet.create(:group => 12345)
110
+
111
+ lambda {@tweet.id}.should raise_error(NoMethodError)
112
+ @tweet.tweet_id.should_not be_nil
113
+ Tweet.table_name.should == 'dynamoid_tests_twitters'
114
+ Tweet.hash_key.should == :tweet_id
115
+ Tweet.read_capacity.should == 200
116
+ Tweet.write_capacity.should == 200
117
+ end
118
+ end
@@ -0,0 +1,127 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
2
+
3
+ describe "Dynamoid::Fields" do
4
+
5
+ before do
6
+ @address = Address.new
7
+ end
8
+
9
+ it 'declares read attributes' do
10
+ @address.city.should be_nil
11
+ end
12
+
13
+ it 'declares write attributes' do
14
+ @address.city = 'Chicago'
15
+ @address.city.should == 'Chicago'
16
+ end
17
+
18
+ it 'declares a query attribute' do
19
+ @address.city?.should be_false
20
+
21
+ @address.city = 'Chicago'
22
+
23
+ @address.city?.should be_true
24
+ end
25
+
26
+ it 'automatically declares id' do
27
+ lambda {@address.id}.should_not raise_error
28
+ end
29
+
30
+ it 'automatically declares and fills in created_at and updated_at' do
31
+ @address.save
32
+
33
+ @address = @address.reload
34
+ @address.created_at.should_not be_nil
35
+ @address.created_at.class.should == DateTime
36
+ @address.updated_at.should_not be_nil
37
+ @address.updated_at.class.should == DateTime
38
+ end
39
+
40
+ context 'with a saved address' do
41
+ before do
42
+ @address = Address.create
43
+ @original_id = @address.id
44
+ end
45
+
46
+ it 'should write an attribute correctly' do
47
+ @address.write_attribute(:city, 'Chicago')
48
+ end
49
+
50
+ it 'should write an attribute with an alias' do
51
+ @address[:city] = 'Chicago'
52
+ end
53
+
54
+ it 'should read a written attribute' do
55
+ @address.write_attribute(:city, 'Chicago')
56
+ @address.read_attribute(:city).should == 'Chicago'
57
+ end
58
+
59
+ it 'should read a written attribute with the alias' do
60
+ @address.write_attribute(:city, 'Chicago')
61
+ @address[:city].should == 'Chicago'
62
+ end
63
+
64
+ it 'should update all attributes' do
65
+ @address.expects(:save).once.returns(true)
66
+ @address.update_attributes(:city => 'Chicago')
67
+ @address[:city].should == 'Chicago'
68
+ @address.id.should == @original_id
69
+ end
70
+
71
+ it 'should update one attribute' do
72
+ @address.expects(:save).once.returns(true)
73
+ @address.update_attribute(:city, 'Chicago')
74
+ @address[:city].should == 'Chicago'
75
+ @address.id.should == @original_id
76
+ end
77
+
78
+ it 'adds in dirty methods for attributes' do
79
+ @address.city = 'Chicago'
80
+ @address.save
81
+
82
+ @address.city = 'San Francisco'
83
+
84
+ @address.city_was.should == 'Chicago'
85
+ end
86
+
87
+ it 'returns all attributes' do
88
+ Address.attributes.should == {:id=>{:type=>:string}, :created_at=>{:type=>:datetime}, :updated_at=>{:type=>:datetime}, :city=>{:type=>:string}, :options=>{:type=>:serialized}}
89
+ end
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
96
+
97
+
98
+ context 'default values for fields' do
99
+ before do
100
+ @clazz = Class.new do
101
+ include Dynamoid::Document
102
+
103
+ field :name, :string, :default => 'x'
104
+ field :uid, :integer, :default => lambda { 42 }
105
+
106
+ def self.name
107
+ 'Document'
108
+ end
109
+ end
110
+
111
+
112
+ @doc = @clazz.new
113
+ end
114
+
115
+ it 'returns default value' do
116
+ @doc.name.should eq('x')
117
+ @doc.uid.should eq(42)
118
+ end
119
+
120
+ it 'should save default value' do
121
+ @doc.save!
122
+ @doc.reload.name.should eq('x')
123
+ @doc.uid.should eq(42)
124
+ end
125
+ end
126
+
127
+ end