dynamoid-moda 0.7.1
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.
- checksums.yaml +15 -0
- data/.document +5 -0
- data/.rspec +1 -0
- data/.travis.yml +7 -0
- data/Gemfile +24 -0
- data/Gemfile.lock +118 -0
- data/Gemfile_activemodel4 +24 -0
- data/Gemfile_activemodel4.lock +88 -0
- data/LICENSE.txt +20 -0
- data/README.markdown +360 -0
- data/Rakefile +93 -0
- data/VERSION +1 -0
- data/doc/.nojekyll +0 -0
- data/doc/Dynamoid.html +328 -0
- data/doc/Dynamoid/Adapter.html +1872 -0
- data/doc/Dynamoid/Adapter/AwsSdk.html +2101 -0
- data/doc/Dynamoid/Adapter/Local.html +1574 -0
- data/doc/Dynamoid/Associations.html +138 -0
- data/doc/Dynamoid/Associations/Association.html +847 -0
- data/doc/Dynamoid/Associations/BelongsTo.html +161 -0
- data/doc/Dynamoid/Associations/ClassMethods.html +766 -0
- data/doc/Dynamoid/Associations/HasAndBelongsToMany.html +167 -0
- data/doc/Dynamoid/Associations/HasMany.html +167 -0
- data/doc/Dynamoid/Associations/HasOne.html +161 -0
- data/doc/Dynamoid/Associations/ManyAssociation.html +1684 -0
- data/doc/Dynamoid/Associations/SingleAssociation.html +627 -0
- data/doc/Dynamoid/Components.html +242 -0
- data/doc/Dynamoid/Config.html +412 -0
- data/doc/Dynamoid/Config/Options.html +638 -0
- data/doc/Dynamoid/Criteria.html +138 -0
- data/doc/Dynamoid/Criteria/Chain.html +1471 -0
- data/doc/Dynamoid/Criteria/ClassMethods.html +105 -0
- data/doc/Dynamoid/Dirty.html +424 -0
- data/doc/Dynamoid/Dirty/ClassMethods.html +174 -0
- data/doc/Dynamoid/Document.html +1033 -0
- data/doc/Dynamoid/Document/ClassMethods.html +1116 -0
- data/doc/Dynamoid/Errors.html +125 -0
- data/doc/Dynamoid/Errors/ConditionalCheckFailedException.html +141 -0
- data/doc/Dynamoid/Errors/DocumentNotValid.html +221 -0
- data/doc/Dynamoid/Errors/Error.html +137 -0
- data/doc/Dynamoid/Errors/InvalidField.html +141 -0
- data/doc/Dynamoid/Errors/InvalidQuery.html +131 -0
- data/doc/Dynamoid/Errors/MissingRangeKey.html +141 -0
- data/doc/Dynamoid/Fields.html +686 -0
- data/doc/Dynamoid/Fields/ClassMethods.html +438 -0
- data/doc/Dynamoid/Finders.html +135 -0
- data/doc/Dynamoid/Finders/ClassMethods.html +943 -0
- data/doc/Dynamoid/IdentityMap.html +492 -0
- data/doc/Dynamoid/IdentityMap/ClassMethods.html +534 -0
- data/doc/Dynamoid/Indexes.html +321 -0
- data/doc/Dynamoid/Indexes/ClassMethods.html +369 -0
- data/doc/Dynamoid/Indexes/Index.html +1142 -0
- data/doc/Dynamoid/Middleware.html +115 -0
- data/doc/Dynamoid/Middleware/IdentityMap.html +264 -0
- data/doc/Dynamoid/Persistence.html +892 -0
- data/doc/Dynamoid/Persistence/ClassMethods.html +836 -0
- data/doc/Dynamoid/Validations.html +415 -0
- data/doc/_index.html +506 -0
- data/doc/class_list.html +53 -0
- data/doc/css/common.css +1 -0
- data/doc/css/full_list.css +57 -0
- data/doc/css/style.css +338 -0
- data/doc/file.LICENSE.html +73 -0
- data/doc/file.README.html +416 -0
- data/doc/file_list.html +58 -0
- data/doc/frames.html +28 -0
- data/doc/index.html +416 -0
- data/doc/js/app.js +214 -0
- data/doc/js/full_list.js +178 -0
- data/doc/js/jquery.js +4 -0
- data/doc/method_list.html +1144 -0
- data/doc/top-level-namespace.html +112 -0
- data/dynamoid-moda.gemspec +210 -0
- data/dynamoid.gemspec +208 -0
- data/lib/dynamoid.rb +46 -0
- data/lib/dynamoid/adapter.rb +267 -0
- data/lib/dynamoid/adapter/aws_sdk.rb +309 -0
- data/lib/dynamoid/associations.rb +106 -0
- data/lib/dynamoid/associations/association.rb +105 -0
- data/lib/dynamoid/associations/belongs_to.rb +44 -0
- data/lib/dynamoid/associations/has_and_belongs_to_many.rb +40 -0
- data/lib/dynamoid/associations/has_many.rb +39 -0
- data/lib/dynamoid/associations/has_one.rb +39 -0
- data/lib/dynamoid/associations/many_association.rb +191 -0
- data/lib/dynamoid/associations/single_association.rb +69 -0
- data/lib/dynamoid/components.rb +37 -0
- data/lib/dynamoid/config.rb +57 -0
- data/lib/dynamoid/config/options.rb +78 -0
- data/lib/dynamoid/criteria.rb +29 -0
- data/lib/dynamoid/criteria/chain.rb +326 -0
- data/lib/dynamoid/dirty.rb +47 -0
- data/lib/dynamoid/document.rb +199 -0
- data/lib/dynamoid/errors.rb +28 -0
- data/lib/dynamoid/fields.rb +138 -0
- data/lib/dynamoid/finders.rb +133 -0
- data/lib/dynamoid/identity_map.rb +96 -0
- data/lib/dynamoid/indexes.rb +69 -0
- data/lib/dynamoid/indexes/index.rb +103 -0
- data/lib/dynamoid/middleware/identity_map.rb +16 -0
- data/lib/dynamoid/persistence.rb +292 -0
- data/lib/dynamoid/validations.rb +36 -0
- data/spec/app/models/address.rb +13 -0
- data/spec/app/models/camel_case.rb +34 -0
- data/spec/app/models/car.rb +6 -0
- data/spec/app/models/magazine.rb +11 -0
- data/spec/app/models/message.rb +9 -0
- data/spec/app/models/nuclear_submarine.rb +5 -0
- data/spec/app/models/sponsor.rb +8 -0
- data/spec/app/models/subscription.rb +12 -0
- data/spec/app/models/tweet.rb +12 -0
- data/spec/app/models/user.rb +26 -0
- data/spec/app/models/vehicle.rb +7 -0
- data/spec/dynamoid/adapter/aws_sdk_spec.rb +376 -0
- data/spec/dynamoid/adapter_spec.rb +155 -0
- data/spec/dynamoid/associations/association_spec.rb +194 -0
- data/spec/dynamoid/associations/belongs_to_spec.rb +71 -0
- data/spec/dynamoid/associations/has_and_belongs_to_many_spec.rb +47 -0
- data/spec/dynamoid/associations/has_many_spec.rb +42 -0
- data/spec/dynamoid/associations/has_one_spec.rb +45 -0
- data/spec/dynamoid/associations_spec.rb +16 -0
- data/spec/dynamoid/config_spec.rb +27 -0
- data/spec/dynamoid/criteria/chain_spec.rb +210 -0
- data/spec/dynamoid/criteria_spec.rb +75 -0
- data/spec/dynamoid/dirty_spec.rb +57 -0
- data/spec/dynamoid/document_spec.rb +180 -0
- data/spec/dynamoid/fields_spec.rb +156 -0
- data/spec/dynamoid/finders_spec.rb +147 -0
- data/spec/dynamoid/identity_map_spec.rb +45 -0
- data/spec/dynamoid/indexes/index_spec.rb +104 -0
- data/spec/dynamoid/indexes_spec.rb +25 -0
- data/spec/dynamoid/persistence_spec.rb +301 -0
- data/spec/dynamoid/validations_spec.rb +36 -0
- data/spec/dynamoid_spec.rb +14 -0
- data/spec/spec_helper.rb +55 -0
- data/spec/support/with_partitioning.rb +15 -0
- metadata +363 -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,34 @@
|
|
|
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
|
+
before_update :doing_before_update
|
|
14
|
+
after_update :doing_after_update
|
|
15
|
+
|
|
16
|
+
private
|
|
17
|
+
|
|
18
|
+
def doing_before_create
|
|
19
|
+
true
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def doing_after_create
|
|
23
|
+
true
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def doing_before_update
|
|
27
|
+
true
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
def doing_after_update
|
|
31
|
+
true
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
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,376 @@
|
|
|
1
|
+
require 'dynamoid/adapter/aws_sdk'
|
|
2
|
+
require File.expand_path(File.dirname(__FILE__) + '../../../spec_helper')
|
|
3
|
+
|
|
4
|
+
describe Dynamoid::Adapter::AwsSdk do
|
|
5
|
+
before(:each) do
|
|
6
|
+
pending "You must have an active DynamoDB connection" unless ENV['ACCESS_KEY'] && ENV['SECRET_KEY']
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
#
|
|
10
|
+
# These let() definitions create tables "dynamoid_tests_TestTable<N>" and return the
|
|
11
|
+
# name of the table. An after(:each) handler drops any tables created this way after each test
|
|
12
|
+
#
|
|
13
|
+
# Name => Constructor args
|
|
14
|
+
{
|
|
15
|
+
1 => [:id],
|
|
16
|
+
2 => [:id],
|
|
17
|
+
3 => [:id, {:range_key => {:range => :number}}],
|
|
18
|
+
4 => [:id, {:range_key => {:range => :number}}]
|
|
19
|
+
}.each do |n, args|
|
|
20
|
+
name = "dynamoid_tests_TestTable#{n}"
|
|
21
|
+
let(:"test_table#{n}") do
|
|
22
|
+
Dynamoid::Adapter.create_table(name, *args)
|
|
23
|
+
@created_tables << name
|
|
24
|
+
name
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
before(:each) { @created_tables = [] }
|
|
29
|
+
after(:each) do
|
|
30
|
+
@created_tables.each do |t|
|
|
31
|
+
Dynamoid::Adapter.delete_table(t)
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
#
|
|
36
|
+
# Returns a random key parition if partitioning is on, or an empty string if
|
|
37
|
+
# it is off, useful for shared examples where partitioning may or may not be on
|
|
38
|
+
#
|
|
39
|
+
def key_partition
|
|
40
|
+
Dynamoid::Config.partitioning? ? ".#{Random.rand(Dynamoid::Config.partition_size)}" : ''
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
#
|
|
44
|
+
# Tests adapter against ranged tables
|
|
45
|
+
#
|
|
46
|
+
shared_examples 'range queries' do
|
|
47
|
+
before do
|
|
48
|
+
Dynamoid::Adapter.put_item(test_table3, {:id => "1#{key_partition}", :range => 1.0})
|
|
49
|
+
Dynamoid::Adapter.put_item(test_table3, {:id => "1#{key_partition}", :range => 3.0})
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
it 'performs query on a table with a range and selects items in a range' do
|
|
53
|
+
Dynamoid::Adapter.query(test_table3, :hash_value => '1', :range_value => 0.0..3.0).to_a.should =~ [{:id => '1', :range => BigDecimal.new(1)}, {:id => '1', :range => BigDecimal.new(3)}]
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
it 'performs query on a table with a range and selects items in a range with :select option' do
|
|
57
|
+
Dynamoid::Adapter.query(test_table3, :hash_value => '1', :range_value => 0.0..3.0, :select => :all).to_a.should =~ [{:id => '1', :range => BigDecimal.new(1)}, {:id => '1', :range => BigDecimal.new(3)}]
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
it 'performs query on a table with a range and selects items greater than' do
|
|
61
|
+
Dynamoid::Adapter.query(test_table3, :hash_value => '1', :range_greater_than => 1.0).to_a.should =~ [{:id => '1', :range => BigDecimal.new(3)}]
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
it 'performs query on a table with a range and selects items less than' do
|
|
65
|
+
Dynamoid::Adapter.query(test_table3, :hash_value => '1', :range_less_than => 2.0).to_a.should =~ [{:id => '1', :range => BigDecimal.new(1)}]
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
it 'performs query on a table with a range and selects items gte' do
|
|
69
|
+
Dynamoid::Adapter.query(test_table3, :hash_value => '1', :range_gte => 1.0).to_a.should =~ [{:id => '1', :range => BigDecimal.new(1)}, {:id => '1', :range => BigDecimal.new(3)}]
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
it 'performs query on a table with a range and selects items lte' do
|
|
73
|
+
Dynamoid::Adapter.query(test_table3, :hash_value => '1', :range_lte => 3.0).to_a.should =~ [{:id => '1', :range => BigDecimal.new(1)}, {:id => '1', :range => BigDecimal.new(3)}]
|
|
74
|
+
end
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
#
|
|
78
|
+
# Tests scan_index_forwards flag behavior on range queries
|
|
79
|
+
#
|
|
80
|
+
shared_examples 'correct ordering' do
|
|
81
|
+
before(:each) do
|
|
82
|
+
pending "Order is not preserved on paritioned tables" if(Dynamoid::Config.partitioning?)
|
|
83
|
+
Dynamoid::Adapter.put_item(test_table4, {:id => "1#{key_partition}", :order => 1, :range => 1.0})
|
|
84
|
+
Dynamoid::Adapter.put_item(test_table4, {:id => "1#{key_partition}", :order => 2, :range => 2.0})
|
|
85
|
+
Dynamoid::Adapter.put_item(test_table4, {:id => "1#{key_partition}", :order => 3, :range => 3.0})
|
|
86
|
+
Dynamoid::Adapter.put_item(test_table4, {:id => "1#{key_partition}", :order => 4, :range => 4.0})
|
|
87
|
+
Dynamoid::Adapter.put_item(test_table4, {:id => "1#{key_partition}", :order => 5, :range => 5.0})
|
|
88
|
+
Dynamoid::Adapter.put_item(test_table4, {:id => "1#{key_partition}", :order => 6, :range => 6.0})
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
it 'performs query on a table with a range and selects items less than that is in the correct order, scan_index_forward true' do
|
|
92
|
+
query = Dynamoid::Adapter.query(test_table4, :hash_value => '1', :range_greater_than => 0, :scan_index_forward => true).to_a
|
|
93
|
+
query[0].should == {:id => '1', :order => 1, :range => BigDecimal.new(1)}
|
|
94
|
+
query[1].should == {:id => '1', :order => 2, :range => BigDecimal.new(2)}
|
|
95
|
+
query[2].should == {:id => '1', :order => 3, :range => BigDecimal.new(3)}
|
|
96
|
+
query[3].should == {:id => '1', :order => 4, :range => BigDecimal.new(4)}
|
|
97
|
+
query[4].should == {:id => '1', :order => 5, :range => BigDecimal.new(5)}
|
|
98
|
+
query[5].should == {:id => '1', :order => 6, :range => BigDecimal.new(6)}
|
|
99
|
+
end
|
|
100
|
+
|
|
101
|
+
it 'performs query on a table with a range and selects items less than that is in the correct order, scan_index_forward false' do
|
|
102
|
+
query = Dynamoid::Adapter.query(test_table4, :hash_value => '1', :range_greater_than => 0, :scan_index_forward => false).to_a
|
|
103
|
+
query[5].should == {:id => '1', :order => 1, :range => BigDecimal.new(1)}
|
|
104
|
+
query[4].should == {:id => '1', :order => 2, :range => BigDecimal.new(2)}
|
|
105
|
+
query[3].should == {:id => '1', :order => 3, :range => BigDecimal.new(3)}
|
|
106
|
+
query[2].should == {:id => '1', :order => 4, :range => BigDecimal.new(4)}
|
|
107
|
+
query[1].should == {:id => '1', :order => 5, :range => BigDecimal.new(5)}
|
|
108
|
+
query[0].should == {:id => '1', :order => 6, :range => BigDecimal.new(6)}
|
|
109
|
+
end
|
|
110
|
+
end
|
|
111
|
+
|
|
112
|
+
|
|
113
|
+
context 'without a preexisting table' do
|
|
114
|
+
# CreateTable and DeleteTable
|
|
115
|
+
it 'performs CreateTable and DeleteTable' do
|
|
116
|
+
table = Dynamoid::Adapter.create_table('CreateTable', :id, :range_key => { :created_at => :number })
|
|
117
|
+
|
|
118
|
+
Dynamoid::Adapter.connection.tables.collect{|t| t.name}.should include 'CreateTable'
|
|
119
|
+
|
|
120
|
+
Dynamoid::Adapter.delete_table('CreateTable')
|
|
121
|
+
end
|
|
122
|
+
end
|
|
123
|
+
|
|
124
|
+
|
|
125
|
+
context 'with a preexisting table without paritioning' do
|
|
126
|
+
# GetItem, PutItem and DeleteItem
|
|
127
|
+
it "performs GetItem for an item that does not exist" do
|
|
128
|
+
Dynamoid::Adapter.get_item(test_table1, '1').should be_nil
|
|
129
|
+
end
|
|
130
|
+
|
|
131
|
+
it "performs GetItem for an item that does exist" do
|
|
132
|
+
Dynamoid::Adapter.put_item(test_table1, {:id => '1', :name => 'Josh'})
|
|
133
|
+
|
|
134
|
+
Dynamoid::Adapter.get_item(test_table1, '1').should == {:name => 'Josh', :id => '1'}
|
|
135
|
+
|
|
136
|
+
Dynamoid::Adapter.delete_item(test_table1, '1')
|
|
137
|
+
|
|
138
|
+
Dynamoid::Adapter.get_item(test_table1, '1').should be_nil
|
|
139
|
+
end
|
|
140
|
+
|
|
141
|
+
it 'performs GetItem for an item that does exist with a range key' do
|
|
142
|
+
Dynamoid::Adapter.put_item(test_table3, {:id => '1', :name => 'Josh', :range => 2.0})
|
|
143
|
+
|
|
144
|
+
Dynamoid::Adapter.get_item(test_table3, '1', :range_key => 2.0).should == {:name => 'Josh', :id => '1', :range => 2.0}
|
|
145
|
+
|
|
146
|
+
Dynamoid::Adapter.delete_item(test_table3, '1', :range_key => 2.0)
|
|
147
|
+
|
|
148
|
+
Dynamoid::Adapter.get_item(test_table3, '1', :range_key => 2.0).should be_nil
|
|
149
|
+
end
|
|
150
|
+
|
|
151
|
+
it 'performs DeleteItem for an item that does not exist' do
|
|
152
|
+
Dynamoid::Adapter.delete_item(test_table1, '1')
|
|
153
|
+
|
|
154
|
+
Dynamoid::Adapter.get_item(test_table1, '1').should be_nil
|
|
155
|
+
end
|
|
156
|
+
|
|
157
|
+
it 'performs PutItem for an item that does not exist' do
|
|
158
|
+
Dynamoid::Adapter.put_item(test_table1, {:id => '1', :name => 'Josh'})
|
|
159
|
+
|
|
160
|
+
Dynamoid::Adapter.get_item(test_table1, '1').should == {:id => '1', :name => 'Josh'}
|
|
161
|
+
end
|
|
162
|
+
|
|
163
|
+
# BatchGetItem
|
|
164
|
+
it 'passes options to underlying BatchGet call' do
|
|
165
|
+
AWS::DynamoDB::BatchGet.any_instance.expects(:table).with(test_table1, :all, ['1', '2'], :consistent_read => true)
|
|
166
|
+
described_class.batch_get_item({test_table1 => ['1', '2']}, :consistent_read => true)
|
|
167
|
+
end
|
|
168
|
+
|
|
169
|
+
it "performs BatchGetItem with singular keys" do
|
|
170
|
+
Dynamoid::Adapter.put_item(test_table1, {:id => '1', :name => 'Josh'})
|
|
171
|
+
Dynamoid::Adapter.put_item(test_table2, {:id => '1', :name => 'Justin'})
|
|
172
|
+
|
|
173
|
+
results = Dynamoid::Adapter.batch_get_item(test_table1 => '1', test_table2 => '1')
|
|
174
|
+
results.size.should == 2
|
|
175
|
+
results[test_table1].should include({:name => 'Josh', :id => '1'})
|
|
176
|
+
results[test_table2].should include({:name => 'Justin', :id => '1'})
|
|
177
|
+
end
|
|
178
|
+
|
|
179
|
+
it "performs BatchGetItem with multiple keys" do
|
|
180
|
+
Dynamoid::Adapter.put_item(test_table1, {:id => '1', :name => 'Josh'})
|
|
181
|
+
Dynamoid::Adapter.put_item(test_table1, {:id => '2', :name => 'Justin'})
|
|
182
|
+
|
|
183
|
+
results = Dynamoid::Adapter.batch_get_item(test_table1 => ['1', '2'])
|
|
184
|
+
results.size.should == 1
|
|
185
|
+
results[test_table1].should include({:name => 'Josh', :id => '1'})
|
|
186
|
+
results[test_table1].should include({:name => 'Justin', :id => '2'})
|
|
187
|
+
end
|
|
188
|
+
|
|
189
|
+
it 'performs BatchGetItem with one ranged key' do
|
|
190
|
+
Dynamoid::Adapter.put_item(test_table3, {:id => '1', :name => 'Josh', :range => 1.0})
|
|
191
|
+
Dynamoid::Adapter.put_item(test_table3, {:id => '2', :name => 'Justin', :range => 2.0})
|
|
192
|
+
|
|
193
|
+
results = Dynamoid::Adapter.batch_get_item(test_table3 => [['1', 1.0]])
|
|
194
|
+
results.size.should == 1
|
|
195
|
+
results[test_table3].should include({:name => 'Josh', :id => '1', :range => 1.0})
|
|
196
|
+
end
|
|
197
|
+
|
|
198
|
+
it 'performs BatchGetItem with multiple ranged keys' do
|
|
199
|
+
Dynamoid::Adapter.put_item(test_table3, {:id => '1', :name => 'Josh', :range => 1.0})
|
|
200
|
+
Dynamoid::Adapter.put_item(test_table3, {:id => '2', :name => 'Justin', :range => 2.0})
|
|
201
|
+
|
|
202
|
+
results = Dynamoid::Adapter.batch_get_item(test_table3 => [['1', 1.0],['2', 2.0]])
|
|
203
|
+
results.size.should == 1
|
|
204
|
+
results[test_table3].should include({:name => 'Josh', :id => '1', :range => 1.0})
|
|
205
|
+
results[test_table3].should include({:name => 'Justin', :id => '2', :range => 2.0})
|
|
206
|
+
end
|
|
207
|
+
|
|
208
|
+
# BatchDeleteItem
|
|
209
|
+
it "performs BatchDeleteItem with singular keys" do
|
|
210
|
+
Dynamoid::Adapter.put_item(test_table1, {:id => '1', :name => 'Josh'})
|
|
211
|
+
Dynamoid::Adapter.put_item(test_table2, {:id => '1', :name => 'Justin'})
|
|
212
|
+
|
|
213
|
+
Dynamoid::Adapter.batch_delete_item(test_table1 => ['1'], test_table2 => ['1'])
|
|
214
|
+
|
|
215
|
+
results = Dynamoid::Adapter.batch_get_item(test_table1 => '1', test_table2 => '1')
|
|
216
|
+
results.size.should == 0
|
|
217
|
+
|
|
218
|
+
results[test_table1].should_not include({:name => 'Josh', :id => '1'})
|
|
219
|
+
results[test_table2].should_not include({:name => 'Justin', :id => '1'})
|
|
220
|
+
end
|
|
221
|
+
|
|
222
|
+
it "performs BatchDeleteItem with multiple keys" do
|
|
223
|
+
Dynamoid::Adapter.put_item(test_table1, {:id => '1', :name => 'Josh'})
|
|
224
|
+
Dynamoid::Adapter.put_item(test_table1, {:id => '2', :name => 'Justin'})
|
|
225
|
+
|
|
226
|
+
Dynamoid::Adapter.batch_delete_item(test_table1 => ['1', '2'])
|
|
227
|
+
|
|
228
|
+
results = Dynamoid::Adapter.batch_get_item(test_table1 => ['1', '2'])
|
|
229
|
+
results.size.should == 0
|
|
230
|
+
|
|
231
|
+
results[test_table1].should_not include({:name => 'Josh', :id => '1'})
|
|
232
|
+
results[test_table1].should_not include({:name => 'Justin', :id => '2'})
|
|
233
|
+
end
|
|
234
|
+
|
|
235
|
+
it 'performs BatchDeleteItem with one ranged key' do
|
|
236
|
+
Dynamoid::Adapter.put_item(test_table3, {:id => '1', :name => 'Josh', :range => 1.0})
|
|
237
|
+
Dynamoid::Adapter.put_item(test_table3, {:id => '2', :name => 'Justin', :range => 2.0})
|
|
238
|
+
|
|
239
|
+
Dynamoid::Adapter.batch_delete_item(test_table3 => [['1', 1.0]])
|
|
240
|
+
results = Dynamoid::Adapter.batch_get_item(test_table3 => [['1', 1.0]])
|
|
241
|
+
results.size.should == 0
|
|
242
|
+
|
|
243
|
+
results[test_table3].should_not include({:name => 'Josh', :id => '1', :range => 1.0})
|
|
244
|
+
end
|
|
245
|
+
|
|
246
|
+
it 'performs BatchDeleteItem with multiple ranged keys' do
|
|
247
|
+
Dynamoid::Adapter.put_item(test_table3, {:id => '1', :name => 'Josh', :range => 1.0})
|
|
248
|
+
Dynamoid::Adapter.put_item(test_table3, {:id => '2', :name => 'Justin', :range => 2.0})
|
|
249
|
+
|
|
250
|
+
Dynamoid::Adapter.batch_delete_item(test_table3 => [['1', 1.0],['2', 2.0]])
|
|
251
|
+
results = Dynamoid::Adapter.batch_get_item(test_table3 => [['1', 1.0],['2', 2.0]])
|
|
252
|
+
results.size.should == 0
|
|
253
|
+
|
|
254
|
+
results[test_table3].should_not include({:name => 'Josh', :id => '1', :range => 1.0})
|
|
255
|
+
results[test_table3].should_not include({:name => 'Justin', :id => '2', :range => 2.0})
|
|
256
|
+
end
|
|
257
|
+
|
|
258
|
+
# ListTables
|
|
259
|
+
it 'performs ListTables' do
|
|
260
|
+
#Force creation of the tables
|
|
261
|
+
test_table1; test_table2; test_table3; test_table4
|
|
262
|
+
|
|
263
|
+
Dynamoid::Adapter.list_tables.should include test_table1
|
|
264
|
+
Dynamoid::Adapter.list_tables.should include test_table2
|
|
265
|
+
end
|
|
266
|
+
|
|
267
|
+
# Query
|
|
268
|
+
it 'performs query on a table and returns items' do
|
|
269
|
+
Dynamoid::Adapter.put_item(test_table1, {:id => '1', :name => 'Josh'})
|
|
270
|
+
|
|
271
|
+
Dynamoid::Adapter.query(test_table1, :hash_value => '1').first.should == { :id=> '1', :name=>"Josh" }
|
|
272
|
+
end
|
|
273
|
+
|
|
274
|
+
it 'performs query on a table and returns items if there are multiple items' do
|
|
275
|
+
Dynamoid::Adapter.put_item(test_table1, {:id => '1', :name => 'Josh'})
|
|
276
|
+
Dynamoid::Adapter.put_item(test_table1, {:id => '2', :name => 'Justin'})
|
|
277
|
+
|
|
278
|
+
Dynamoid::Adapter.query(test_table1, :hash_value => '1').first.should == { :id=> '1', :name=>"Josh" }
|
|
279
|
+
end
|
|
280
|
+
|
|
281
|
+
it_behaves_like 'range queries'
|
|
282
|
+
|
|
283
|
+
# Scan
|
|
284
|
+
it 'performs scan on a table and returns items' do
|
|
285
|
+
Dynamoid::Adapter.put_item(test_table1, {:id => '1', :name => 'Josh'})
|
|
286
|
+
|
|
287
|
+
Dynamoid::Adapter.scan(test_table1, :name => 'Josh').to_a.should == [{ :id=> '1', :name=>"Josh" }]
|
|
288
|
+
end
|
|
289
|
+
|
|
290
|
+
it 'performs scan on a table and returns items if there are multiple items but only one match' do
|
|
291
|
+
Dynamoid::Adapter.put_item(test_table1, {:id => '1', :name => 'Josh'})
|
|
292
|
+
Dynamoid::Adapter.put_item(test_table1, {:id => '2', :name => 'Justin'})
|
|
293
|
+
|
|
294
|
+
Dynamoid::Adapter.scan(test_table1, :name => 'Josh').to_a.should == [{ :id=> '1', :name=>"Josh" }]
|
|
295
|
+
end
|
|
296
|
+
|
|
297
|
+
it 'performs scan on a table and returns multiple items if there are multiple matches' do
|
|
298
|
+
Dynamoid::Adapter.put_item(test_table1, {:id => '1', :name => 'Josh'})
|
|
299
|
+
Dynamoid::Adapter.put_item(test_table1, {:id => '2', :name => 'Josh'})
|
|
300
|
+
|
|
301
|
+
Dynamoid::Adapter.scan(test_table1, :name => 'Josh').should include({:name=>"Josh", :id=>"2"}, {:name=>"Josh", :id=>"1"})
|
|
302
|
+
end
|
|
303
|
+
|
|
304
|
+
it 'performs scan on a table and returns all items if no criteria are specified' do
|
|
305
|
+
Dynamoid::Adapter.put_item(test_table1, {:id => '1', :name => 'Josh'})
|
|
306
|
+
Dynamoid::Adapter.put_item(test_table1, {:id => '2', :name => 'Josh'})
|
|
307
|
+
|
|
308
|
+
Dynamoid::Adapter.scan(test_table1, {}).should include({:name=>"Josh", :id=>"2"}, {:name=>"Josh", :id=>"1"})
|
|
309
|
+
end
|
|
310
|
+
|
|
311
|
+
it_behaves_like 'correct ordering'
|
|
312
|
+
end
|
|
313
|
+
|
|
314
|
+
context 'with a preexisting table with paritioning' do
|
|
315
|
+
before(:all) do
|
|
316
|
+
@previous_value = Dynamoid::Config.partitioning
|
|
317
|
+
Dynamoid::Config.partitioning = true
|
|
318
|
+
end
|
|
319
|
+
|
|
320
|
+
after(:all) do
|
|
321
|
+
Dynamoid::Config.partitioning = @previous_value
|
|
322
|
+
end
|
|
323
|
+
|
|
324
|
+
# Query
|
|
325
|
+
it 'performs query on a table and returns items' do
|
|
326
|
+
Dynamoid::Adapter.put_item(test_table1, {:id => '1.1', :name => 'Josh'})
|
|
327
|
+
|
|
328
|
+
Dynamoid::Adapter.query(test_table1, :hash_value => '1').first.should == { :id=> '1', :name=>"Josh" }
|
|
329
|
+
end
|
|
330
|
+
|
|
331
|
+
it 'performs query on a table and returns items if there are multiple items' do
|
|
332
|
+
Dynamoid::Adapter.put_item(test_table1, {:id => '1.1', :name => 'Josh'})
|
|
333
|
+
Dynamoid::Adapter.put_item(test_table1, {:id => '2.1', :name => 'Justin'})
|
|
334
|
+
|
|
335
|
+
Dynamoid::Adapter.query(test_table1, :hash_value => '1').first.should == { :id=> '1', :name=>"Josh" }
|
|
336
|
+
end
|
|
337
|
+
|
|
338
|
+
it_behaves_like 'range queries'
|
|
339
|
+
|
|
340
|
+
# Scan
|
|
341
|
+
it 'performs scan on a table and returns items' do
|
|
342
|
+
Dynamoid::Adapter.put_item(test_table1, {:id => '1.1', :name => 'Josh'})
|
|
343
|
+
|
|
344
|
+
Dynamoid::Adapter.scan(test_table1, :name => 'Josh').should == [{ :id=> '1', :name=>"Josh" }]
|
|
345
|
+
end
|
|
346
|
+
|
|
347
|
+
it 'performs scan on a table and returns items if there are multiple items but only one match' do
|
|
348
|
+
Dynamoid::Adapter.put_item(test_table1, {:id => '1.1', :name => 'Josh'})
|
|
349
|
+
Dynamoid::Adapter.put_item(test_table1, {:id => '2.1', :name => 'Justin'})
|
|
350
|
+
|
|
351
|
+
Dynamoid::Adapter.scan(test_table1, :name => 'Josh').should == [{ :id=> '1', :name=>"Josh" }]
|
|
352
|
+
end
|
|
353
|
+
|
|
354
|
+
it 'performs scan on a table and returns multiple items if there are multiple matches' do
|
|
355
|
+
Dynamoid::Adapter.put_item(test_table1, {:id => '1.1', :name => 'Josh'})
|
|
356
|
+
Dynamoid::Adapter.put_item(test_table1, {:id => '2.1', :name => 'Josh'})
|
|
357
|
+
|
|
358
|
+
Dynamoid::Adapter.scan(test_table1, :name => 'Josh').should include({:name=>"Josh", :id=>"2"}, {:name=>"Josh", :id=>"1"})
|
|
359
|
+
end
|
|
360
|
+
|
|
361
|
+
it 'performs scan on a table and returns all items if no criteria are specified' do
|
|
362
|
+
Dynamoid::Adapter.put_item(test_table1, {:id => '1.1', :name => 'Josh'})
|
|
363
|
+
Dynamoid::Adapter.put_item(test_table1, {:id => '2.1', :name => 'Josh'})
|
|
364
|
+
|
|
365
|
+
Dynamoid::Adapter.scan(test_table1, {}).should include({:name=>"Josh", :id=>"2"}, {:name=>"Josh", :id=>"1"})
|
|
366
|
+
end
|
|
367
|
+
|
|
368
|
+
it_behaves_like 'correct ordering'
|
|
369
|
+
end
|
|
370
|
+
|
|
371
|
+
# DescribeTable
|
|
372
|
+
|
|
373
|
+
# UpdateItem
|
|
374
|
+
|
|
375
|
+
# UpdateTable
|
|
376
|
+
end
|