adept_dynamoid 0.5.0.6

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.
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,36 @@
1
+ # encoding: utf-8
2
+ module Dynamoid
3
+
4
+ # Provide ActiveModel validations to Dynamoid documents.
5
+ module Validations
6
+ extend ActiveSupport::Concern
7
+
8
+ include ActiveModel::Validations
9
+ include ActiveModel::Validations::Callbacks
10
+
11
+ # Override save to provide validation support.
12
+ #
13
+ # @since 0.2.0
14
+ def save(options = {})
15
+ options.reverse_merge!(:validate => true)
16
+ return false if options[:validate] and (not valid?)
17
+ super
18
+ end
19
+
20
+ # Is this object valid?
21
+ #
22
+ # @since 0.2.0
23
+ def valid?(context = nil)
24
+ context ||= (new_record? ? :create : :update)
25
+ super(context)
26
+ end
27
+
28
+ # Raise an error unless this object is valid.
29
+ #
30
+ # @since 0.2.0
31
+ def save!
32
+ raise Dynamoid::Errors::DocumentNotValid.new(self) unless valid?
33
+ save(:validate => false)
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,10 @@
1
+ class Address
2
+ include Dynamoid::Document
3
+
4
+ field :city
5
+ field :options, :serialized
6
+
7
+ def zip_code=(zip_code)
8
+ self.city = "Chicago"
9
+ end
10
+ end
@@ -0,0 +1,24 @@
1
+ class CamelCase
2
+ include Dynamoid::Document
3
+
4
+ field :color
5
+
6
+ belongs_to :magazine
7
+ has_many :users
8
+ has_one :sponsor
9
+ has_and_belongs_to_many :subscriptions
10
+
11
+ before_create :doing_before_create
12
+ after_create :doing_after_create
13
+
14
+ private
15
+
16
+ def doing_before_create
17
+ true
18
+ end
19
+
20
+ def doing_after_create
21
+ true
22
+ end
23
+
24
+ end
@@ -0,0 +1,11 @@
1
+ class Magazine
2
+ include Dynamoid::Document
3
+
4
+ field :title
5
+
6
+ has_many :subscriptions
7
+ has_many :camel_cases
8
+ has_one :sponsor
9
+
10
+ belongs_to :owner, :class_name => 'User', :inverse_of => :books
11
+ end
@@ -0,0 +1,9 @@
1
+ class Message
2
+ include Dynamoid::Document
3
+
4
+ table name: :messages, key: :message_id, read_capacity: 200, write_capacity: 200
5
+
6
+ range :time, :datetime
7
+
8
+ field :text
9
+ end
@@ -0,0 +1,8 @@
1
+ class Sponsor
2
+ include Dynamoid::Document
3
+
4
+ belongs_to :magazine
5
+ has_many :subscriptions
6
+
7
+ belongs_to :camel_case
8
+ end
@@ -0,0 +1,12 @@
1
+ class Subscription
2
+ include Dynamoid::Document
3
+
4
+ field :length, :integer
5
+
6
+ belongs_to :magazine
7
+ has_and_belongs_to_many :users
8
+
9
+ belongs_to :customer, :class_name => 'User', :inverse_of => :monthly
10
+
11
+ has_and_belongs_to_many :camel_cases
12
+ end
@@ -0,0 +1,12 @@
1
+ class Tweet
2
+ include Dynamoid::Document
3
+
4
+ table name: :twitters, key: :tweet_id, read_capacity: 200, write_capacity: 200
5
+
6
+ range :group, :string
7
+
8
+ field :msg
9
+ field :count, :integer
10
+ field :tags, :set
11
+ field :user_name
12
+ end
@@ -0,0 +1,26 @@
1
+ class User
2
+ include Dynamoid::Document
3
+
4
+ field :name
5
+ field :email
6
+ field :password
7
+ field :last_logged_in_at, :datetime
8
+
9
+ index :name
10
+ index :email
11
+ index [:name, :email]
12
+ index :name, :range_key => :created_at
13
+ index :name, :range_key => :last_logged_in_at
14
+ index :created_at, :range => true
15
+
16
+ has_and_belongs_to_many :subscriptions
17
+
18
+ has_many :books, :class_name => 'Magazine', :inverse_of => :owner
19
+ has_one :monthly, :class_name => 'Subscription', :inverse_of => :customer
20
+
21
+ has_and_belongs_to_many :followers, :class_name => 'User', :inverse_of => :following
22
+ has_and_belongs_to_many :following, :class_name => 'User', :inverse_of => :followers
23
+
24
+ belongs_to :camel_case
25
+
26
+ end
@@ -0,0 +1,186 @@
1
+ require 'dynamoid/adapter/aws_sdk'
2
+ require File.expand_path(File.dirname(__FILE__) + '../../../spec_helper')
3
+
4
+ describe Dynamoid::Adapter::AwsSdk do
5
+
6
+ if ENV['ACCESS_KEY'] && ENV['SECRET_KEY']
7
+
8
+ context 'without a preexisting table' do
9
+ # CreateTable and DeleteTable
10
+ it 'performs CreateTable and DeleteTable' do
11
+ table = Dynamoid::Adapter.create_table('CreateTable', :id, :range_key => { :created_at => :number })
12
+
13
+ Dynamoid::Adapter.connection.tables.collect{|t| t.name}.should include 'CreateTable'
14
+
15
+ Dynamoid::Adapter.delete_table('CreateTable')
16
+ end
17
+ end
18
+
19
+ context 'with a preexisting table' do
20
+ before(:all) do
21
+ Dynamoid::Adapter.create_table('dynamoid_tests_TestTable1', :id) unless Dynamoid::Adapter.list_tables.include?('dynamoid_tests_TestTable1')
22
+ Dynamoid::Adapter.create_table('dynamoid_tests_TestTable2', :id) unless Dynamoid::Adapter.list_tables.include?('dynamoid_tests_TestTable2')
23
+ Dynamoid::Adapter.create_table('dynamoid_tests_TestTable3', :id, :range_key => { :range => :number }) unless Dynamoid::Adapter.list_tables.include?('dynamoid_tests_TestTable3')
24
+ end
25
+
26
+ # GetItem, PutItem and DeleteItem
27
+ it "performs GetItem for an item that does not exist" do
28
+ Dynamoid::Adapter.get_item('dynamoid_tests_TestTable1', '1').should be_nil
29
+ end
30
+
31
+ it "performs GetItem for an item that does exist" do
32
+ Dynamoid::Adapter.put_item('dynamoid_tests_TestTable1', {:id => '1', :name => 'Josh'})
33
+
34
+ Dynamoid::Adapter.get_item('dynamoid_tests_TestTable1', '1').should == {:name => 'Josh', :id => '1'}
35
+
36
+ Dynamoid::Adapter.delete_item('dynamoid_tests_TestTable1', '1')
37
+
38
+ Dynamoid::Adapter.get_item('dynamoid_tests_TestTable1', '1').should be_nil
39
+ end
40
+
41
+ it 'performs GetItem for an item that does exist with a range key' do
42
+ Dynamoid::Adapter.put_item('dynamoid_tests_TestTable3', {:id => '1', :name => 'Josh', :range => 2.0})
43
+
44
+ Dynamoid::Adapter.get_item('dynamoid_tests_TestTable3', '1', :range_key => 2.0).should == {:name => 'Josh', :id => '1', :range => 2.0}
45
+
46
+ Dynamoid::Adapter.delete_item('dynamoid_tests_TestTable3', '1', :range_key => 2.0)
47
+
48
+ Dynamoid::Adapter.get_item('dynamoid_tests_TestTable3', '1', :range_key => 2.0).should be_nil
49
+ end
50
+
51
+ it 'performs DeleteItem for an item that does not exist' do
52
+ Dynamoid::Adapter.delete_item('dynamoid_tests_TestTable1', '1')
53
+
54
+ Dynamoid::Adapter.get_item('dynamoid_tests_TestTable1', '1').should be_nil
55
+ end
56
+
57
+ it 'performs PutItem for an item that does not exist' do
58
+ Dynamoid::Adapter.put_item('dynamoid_tests_TestTable1', {:id => '1', :name => 'Josh'})
59
+
60
+ Dynamoid::Adapter.get_item('dynamoid_tests_TestTable1', '1').should == {:id => '1', :name => 'Josh'}
61
+ end
62
+
63
+ # BatchGetItem
64
+ it "performs BatchGetItem with singular keys" do
65
+ Dynamoid::Adapter.put_item('dynamoid_tests_TestTable1', {:id => '1', :name => 'Josh'})
66
+ Dynamoid::Adapter.put_item('dynamoid_tests_TestTable2', {:id => '1', :name => 'Justin'})
67
+
68
+ results = Dynamoid::Adapter.batch_get_item('dynamoid_tests_TestTable1' => '1', 'dynamoid_tests_TestTable2' => '1')
69
+ results.size.should == 2
70
+ results['dynamoid_tests_TestTable1'].should include({:name => 'Josh', :id => '1'})
71
+ results['dynamoid_tests_TestTable2'].should include({:name => 'Justin', :id => '1'})
72
+ end
73
+
74
+ it "performs BatchGetItem with multiple keys" do
75
+ Dynamoid::Adapter.put_item('dynamoid_tests_TestTable1', {:id => '1', :name => 'Josh'})
76
+ Dynamoid::Adapter.put_item('dynamoid_tests_TestTable1', {:id => '2', :name => 'Justin'})
77
+
78
+ results = Dynamoid::Adapter.batch_get_item('dynamoid_tests_TestTable1' => ['1', '2'])
79
+ results.size.should == 1
80
+ results['dynamoid_tests_TestTable1'].should include({:name => 'Josh', :id => '1'})
81
+ results['dynamoid_tests_TestTable1'].should include({:name => 'Justin', :id => '2'})
82
+ end
83
+
84
+ it 'performs BatchGetItem with one ranged key' do
85
+ Dynamoid::Adapter.put_item('dynamoid_tests_TestTable3', {:id => '1', :name => 'Josh', :range => 1.0})
86
+ Dynamoid::Adapter.put_item('dynamoid_tests_TestTable3', {:id => '2', :name => 'Justin', :range => 2.0})
87
+
88
+ results = Dynamoid::Adapter.batch_get_item('dynamoid_tests_TestTable3' => [['1', 1.0]])
89
+ results.size.should == 1
90
+ results['dynamoid_tests_TestTable3'].should include({:name => 'Josh', :id => '1', :range => 1.0})
91
+ end
92
+
93
+ it 'performs BatchGetItem with multiple ranged keys' do
94
+ Dynamoid::Adapter.put_item('dynamoid_tests_TestTable3', {:id => '1', :name => 'Josh', :range => 1.0})
95
+ Dynamoid::Adapter.put_item('dynamoid_tests_TestTable3', {:id => '2', :name => 'Justin', :range => 2.0})
96
+
97
+ results = Dynamoid::Adapter.batch_get_item('dynamoid_tests_TestTable3' => [['1', 1.0],['2', 2.0]])
98
+ results.size.should == 1
99
+ results['dynamoid_tests_TestTable3'].should include({:name => 'Josh', :id => '1', :range => 1.0})
100
+ results['dynamoid_tests_TestTable3'].should include({:name => 'Justin', :id => '2', :range => 2.0})
101
+ end
102
+
103
+ # ListTables
104
+ it 'performs ListTables' do
105
+ Dynamoid::Adapter.list_tables.should include 'dynamoid_tests_TestTable1'
106
+ Dynamoid::Adapter.list_tables.should include 'dynamoid_tests_TestTable2'
107
+ end
108
+
109
+ # Query
110
+ it 'performs query on a table and returns items' do
111
+ Dynamoid::Adapter.put_item('dynamoid_tests_TestTable1', {:id => '1', :name => 'Josh'})
112
+
113
+ Dynamoid::Adapter.query('dynamoid_tests_TestTable1', :hash_value => '1').should == { :id=> '1', :name=>"Josh" }
114
+ end
115
+
116
+ it 'performs query on a table and returns items if there are multiple items' do
117
+ Dynamoid::Adapter.put_item('dynamoid_tests_TestTable1', {:id => '1', :name => 'Josh'})
118
+ Dynamoid::Adapter.put_item('dynamoid_tests_TestTable1', {:id => '2', :name => 'Justin'})
119
+
120
+ Dynamoid::Adapter.query('dynamoid_tests_TestTable1', :hash_value => '1').should == { :id=> '1', :name=>"Josh" }
121
+ end
122
+
123
+ context 'range queries' do
124
+ before do
125
+ Dynamoid::Adapter.put_item('dynamoid_tests_TestTable3', {:id => '1', :range => 1.0})
126
+ Dynamoid::Adapter.put_item('dynamoid_tests_TestTable3', {:id => '1', :range => 3.0})
127
+ end
128
+
129
+ it 'performs query on a table with a range and selects items in a range' do
130
+ Dynamoid::Adapter.query('dynamoid_tests_TestTable3', :hash_value => '1', :range_value => 0.0..3.0).should =~ [{:id => '1', :range => BigDecimal.new(1)}, {:id => '1', :range => BigDecimal.new(3)}]
131
+ end
132
+
133
+ it 'performs query on a table with a range and selects items greater than' do
134
+ Dynamoid::Adapter.query('dynamoid_tests_TestTable3', :hash_value => '1', :range_greater_than => 1.0).should =~ [{:id => '1', :range => BigDecimal.new(3)}]
135
+ end
136
+
137
+ it 'performs query on a table with a range and selects items less than' do
138
+ Dynamoid::Adapter.query('dynamoid_tests_TestTable3', :hash_value => '1', :range_less_than => 2.0).should =~ [{:id => '1', :range => BigDecimal.new(1)}]
139
+ end
140
+
141
+ it 'performs query on a table with a range and selects items gte' do
142
+ Dynamoid::Adapter.query('dynamoid_tests_TestTable3', :hash_value => '1', :range_gte => 1.0).should =~ [{:id => '1', :range => BigDecimal.new(1)}, {:id => '1', :range => BigDecimal.new(3)}]
143
+ end
144
+
145
+ it 'performs query on a table with a range and selects items lte' do
146
+ Dynamoid::Adapter.query('dynamoid_tests_TestTable3', :hash_value => '1', :range_lte => 3.0).should =~ [{:id => '1', :range => BigDecimal.new(1)}, {:id => '1', :range => BigDecimal.new(3)}]
147
+ end
148
+ end
149
+
150
+ # Scan
151
+ it 'performs scan on a table and returns items' do
152
+ Dynamoid::Adapter.put_item('dynamoid_tests_TestTable1', {:id => '1', :name => 'Josh'})
153
+
154
+ Dynamoid::Adapter.scan('dynamoid_tests_TestTable1', :name => 'Josh').should == [{ :id=> '1', :name=>"Josh" }]
155
+ end
156
+
157
+ it 'performs scan on a table and returns items if there are multiple items but only one match' do
158
+ Dynamoid::Adapter.put_item('dynamoid_tests_TestTable1', {:id => '1', :name => 'Josh'})
159
+ Dynamoid::Adapter.put_item('dynamoid_tests_TestTable1', {:id => '2', :name => 'Justin'})
160
+
161
+ Dynamoid::Adapter.scan('dynamoid_tests_TestTable1', :name => 'Josh').should == [{ :id=> '1', :name=>"Josh" }]
162
+ end
163
+
164
+ it 'performs scan on a table and returns multiple items if there are multiple matches' do
165
+ Dynamoid::Adapter.put_item('dynamoid_tests_TestTable1', {:id => '1', :name => 'Josh'})
166
+ Dynamoid::Adapter.put_item('dynamoid_tests_TestTable1', {:id => '2', :name => 'Josh'})
167
+
168
+ Dynamoid::Adapter.scan('dynamoid_tests_TestTable1', :name => 'Josh').should include({:name=>"Josh", :id=>"2"}, {:name=>"Josh", :id=>"1"})
169
+ end
170
+
171
+ it 'performs scan on a table and returns all items if no criteria are specified' do
172
+ Dynamoid::Adapter.put_item('dynamoid_tests_TestTable1', {:id => '1', :name => 'Josh'})
173
+ Dynamoid::Adapter.put_item('dynamoid_tests_TestTable1', {:id => '2', :name => 'Josh'})
174
+
175
+ Dynamoid::Adapter.scan('dynamoid_tests_TestTable1', {}).should include({:name=>"Josh", :id=>"2"}, {:name=>"Josh", :id=>"1"})
176
+ end
177
+ end
178
+
179
+ # DescribeTable
180
+
181
+ # UpdateItem
182
+
183
+ # UpdateTable
184
+
185
+ end
186
+ end
@@ -0,0 +1,117 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
2
+
3
+ describe "Dynamoid::Adapter" do
4
+
5
+ before(:all) do
6
+ Dynamoid::Adapter.create_table('dynamoid_tests_TestTable', :id) unless Dynamoid::Adapter.list_tables.include?('dynamoid_tests_TestTable')
7
+ end
8
+
9
+ it 'extends itself automatically' do
10
+ lambda {Dynamoid::Adapter.list_tables}.should_not raise_error
11
+ end
12
+
13
+ it 'raises nomethod if we try a method that is not on the child' do
14
+ lambda {Dynamoid::Adapter.foobar}.should raise_error
15
+ end
16
+
17
+ context 'without partioning' do
18
+ before(:all) do
19
+ @previous_value = Dynamoid::Config.partitioning
20
+ Dynamoid::Config.partitioning = false
21
+ end
22
+
23
+ after(:all) do
24
+ Dynamoid::Config.partitioning = @previous_value
25
+ end
26
+
27
+ it 'writes through the adapter' do
28
+ Dynamoid::Adapter.expects(:put_item).with('dynamoid_tests_TestTable', {:id => '123'}).returns(true)
29
+
30
+ Dynamoid::Adapter.write('dynamoid_tests_TestTable', {:id => '123'})
31
+ end
32
+
33
+ it 'reads through the adapter for one ID' do
34
+ Dynamoid::Adapter.expects(:get_item).with('dynamoid_tests_TestTable', '123', {}).returns(true)
35
+
36
+ Dynamoid::Adapter.read('dynamoid_tests_TestTable', '123')
37
+ end
38
+
39
+ it 'reads through the adapter for many IDs' do
40
+ Dynamoid::Adapter.expects(:batch_get_item).with({'dynamoid_tests_TestTable' => ['1', '2']}).returns(true)
41
+
42
+ Dynamoid::Adapter.read('dynamoid_tests_TestTable', ['1', '2'])
43
+ end
44
+
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', :range_key => 2.0).returns(true)
47
+
48
+ Dynamoid::Adapter.read('dynamoid_tests_TestTable', '123', :range_key => 2.0)
49
+ end
50
+
51
+ it 'reads through the adapter for many IDs and a range key' do
52
+ Dynamoid::Adapter.expects(:batch_get_item).with({'dynamoid_tests_TestTable' => [['1', 2.0], ['2', 2.0]]}).returns(true)
53
+
54
+ Dynamoid::Adapter.read('dynamoid_tests_TestTable', ['1', '2'], :range_key => 2.0)
55
+ end
56
+ end
57
+
58
+ context 'with partitioning' do
59
+ before(:all) do
60
+ @previous_value = Dynamoid::Config.partitioning
61
+ Dynamoid::Config.partitioning = true
62
+ end
63
+
64
+ after(:all) do
65
+ Dynamoid::Config.partitioning = @previous_value
66
+ end
67
+
68
+ it 'writes through the adapter' do
69
+ Random.expects(:rand).with(Dynamoid::Config.partition_size).once.returns(0)
70
+ Dynamoid::Adapter.write('dynamoid_tests_TestTable', {:id => 'testid'})
71
+
72
+ Dynamoid::Adapter.get_item('dynamoid_tests_TestTable', 'testid.0')[:id].should == 'testid.0'
73
+ Dynamoid::Adapter.get_item('dynamoid_tests_TestTable', 'testid.0')[:updated_at].should_not be_nil
74
+ end
75
+
76
+ it 'reads through the adapter for one ID' do
77
+ Dynamoid::Adapter.expects(:batch_get_item).with('dynamoid_tests_TestTable' => (0...Dynamoid::Config.partition_size).collect{|n| "123.#{n}"}).returns({})
78
+
79
+ Dynamoid::Adapter.read('dynamoid_tests_TestTable', '123')
80
+ end
81
+
82
+ it 'reads through the adapter for many IDs' do
83
+ Dynamoid::Adapter.expects(:batch_get_item).with('dynamoid_tests_TestTable' => (0...Dynamoid::Config.partition_size).collect{|n| "1.#{n}"} + (0...Dynamoid::Config.partition_size).collect{|n| "2.#{n}"}).returns({})
84
+
85
+ Dynamoid::Adapter.read('dynamoid_tests_TestTable', ['1', '2'])
86
+ end
87
+
88
+ it 'reads through the adapter for one ID and a range key' do
89
+ Dynamoid::Adapter.expects(:batch_get_item).with('dynamoid_tests_TestTable' => (0...Dynamoid::Config.partition_size).collect{|n| ["123.#{n}", 2.0]}).returns({})
90
+
91
+ Dynamoid::Adapter.read('dynamoid_tests_TestTable', '123', :range_key => 2.0)
92
+ end
93
+
94
+ it 'reads through the adapter for many IDs and a range key' do
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
+
97
+ Dynamoid::Adapter.read('dynamoid_tests_TestTable', ['1', '2'], :range_key => 2.0)
98
+ end
99
+
100
+ it 'returns an ID with all partitions' do
101
+ Dynamoid::Adapter.id_with_partitions('1').should =~ (0...Dynamoid::Config.partition_size).collect{|n| "1.#{n}"}
102
+ end
103
+
104
+ it 'returns an ID and range key with all partitions' do
105
+ Dynamoid::Adapter.id_with_partitions([['1', 1.0]]).should =~ (0...Dynamoid::Config.partition_size).collect{|n| ["1.#{n}", 1.0]}
106
+ end
107
+
108
+ it 'returns a result for one partitioned element' do
109
+ @time = DateTime.now
110
+ @array =[{:id => '1.0', :updated_at => @time - 6.hours}, {:id => '1.1', :updated_at => @time - 3.hours}, {:id => '1.2', :updated_at => @time - 1.hour}, {:id => '1.3', :updated_at => @time - 6.hours}, {:id => '2.0', :updated_at => @time}]
111
+
112
+ Dynamoid::Adapter.result_for_partition(@array).should =~ [{:id => '1', :updated_at => @time - 1.hour}, {:id => '2', :updated_at => @time}]
113
+ end
114
+
115
+ end
116
+
117
+ end