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,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