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.
Files changed (136) hide show
  1. checksums.yaml +15 -0
  2. data/.document +5 -0
  3. data/.rspec +1 -0
  4. data/.travis.yml +7 -0
  5. data/Gemfile +24 -0
  6. data/Gemfile.lock +118 -0
  7. data/Gemfile_activemodel4 +24 -0
  8. data/Gemfile_activemodel4.lock +88 -0
  9. data/LICENSE.txt +20 -0
  10. data/README.markdown +360 -0
  11. data/Rakefile +93 -0
  12. data/VERSION +1 -0
  13. data/doc/.nojekyll +0 -0
  14. data/doc/Dynamoid.html +328 -0
  15. data/doc/Dynamoid/Adapter.html +1872 -0
  16. data/doc/Dynamoid/Adapter/AwsSdk.html +2101 -0
  17. data/doc/Dynamoid/Adapter/Local.html +1574 -0
  18. data/doc/Dynamoid/Associations.html +138 -0
  19. data/doc/Dynamoid/Associations/Association.html +847 -0
  20. data/doc/Dynamoid/Associations/BelongsTo.html +161 -0
  21. data/doc/Dynamoid/Associations/ClassMethods.html +766 -0
  22. data/doc/Dynamoid/Associations/HasAndBelongsToMany.html +167 -0
  23. data/doc/Dynamoid/Associations/HasMany.html +167 -0
  24. data/doc/Dynamoid/Associations/HasOne.html +161 -0
  25. data/doc/Dynamoid/Associations/ManyAssociation.html +1684 -0
  26. data/doc/Dynamoid/Associations/SingleAssociation.html +627 -0
  27. data/doc/Dynamoid/Components.html +242 -0
  28. data/doc/Dynamoid/Config.html +412 -0
  29. data/doc/Dynamoid/Config/Options.html +638 -0
  30. data/doc/Dynamoid/Criteria.html +138 -0
  31. data/doc/Dynamoid/Criteria/Chain.html +1471 -0
  32. data/doc/Dynamoid/Criteria/ClassMethods.html +105 -0
  33. data/doc/Dynamoid/Dirty.html +424 -0
  34. data/doc/Dynamoid/Dirty/ClassMethods.html +174 -0
  35. data/doc/Dynamoid/Document.html +1033 -0
  36. data/doc/Dynamoid/Document/ClassMethods.html +1116 -0
  37. data/doc/Dynamoid/Errors.html +125 -0
  38. data/doc/Dynamoid/Errors/ConditionalCheckFailedException.html +141 -0
  39. data/doc/Dynamoid/Errors/DocumentNotValid.html +221 -0
  40. data/doc/Dynamoid/Errors/Error.html +137 -0
  41. data/doc/Dynamoid/Errors/InvalidField.html +141 -0
  42. data/doc/Dynamoid/Errors/InvalidQuery.html +131 -0
  43. data/doc/Dynamoid/Errors/MissingRangeKey.html +141 -0
  44. data/doc/Dynamoid/Fields.html +686 -0
  45. data/doc/Dynamoid/Fields/ClassMethods.html +438 -0
  46. data/doc/Dynamoid/Finders.html +135 -0
  47. data/doc/Dynamoid/Finders/ClassMethods.html +943 -0
  48. data/doc/Dynamoid/IdentityMap.html +492 -0
  49. data/doc/Dynamoid/IdentityMap/ClassMethods.html +534 -0
  50. data/doc/Dynamoid/Indexes.html +321 -0
  51. data/doc/Dynamoid/Indexes/ClassMethods.html +369 -0
  52. data/doc/Dynamoid/Indexes/Index.html +1142 -0
  53. data/doc/Dynamoid/Middleware.html +115 -0
  54. data/doc/Dynamoid/Middleware/IdentityMap.html +264 -0
  55. data/doc/Dynamoid/Persistence.html +892 -0
  56. data/doc/Dynamoid/Persistence/ClassMethods.html +836 -0
  57. data/doc/Dynamoid/Validations.html +415 -0
  58. data/doc/_index.html +506 -0
  59. data/doc/class_list.html +53 -0
  60. data/doc/css/common.css +1 -0
  61. data/doc/css/full_list.css +57 -0
  62. data/doc/css/style.css +338 -0
  63. data/doc/file.LICENSE.html +73 -0
  64. data/doc/file.README.html +416 -0
  65. data/doc/file_list.html +58 -0
  66. data/doc/frames.html +28 -0
  67. data/doc/index.html +416 -0
  68. data/doc/js/app.js +214 -0
  69. data/doc/js/full_list.js +178 -0
  70. data/doc/js/jquery.js +4 -0
  71. data/doc/method_list.html +1144 -0
  72. data/doc/top-level-namespace.html +112 -0
  73. data/dynamoid-moda.gemspec +210 -0
  74. data/dynamoid.gemspec +208 -0
  75. data/lib/dynamoid.rb +46 -0
  76. data/lib/dynamoid/adapter.rb +267 -0
  77. data/lib/dynamoid/adapter/aws_sdk.rb +309 -0
  78. data/lib/dynamoid/associations.rb +106 -0
  79. data/lib/dynamoid/associations/association.rb +105 -0
  80. data/lib/dynamoid/associations/belongs_to.rb +44 -0
  81. data/lib/dynamoid/associations/has_and_belongs_to_many.rb +40 -0
  82. data/lib/dynamoid/associations/has_many.rb +39 -0
  83. data/lib/dynamoid/associations/has_one.rb +39 -0
  84. data/lib/dynamoid/associations/many_association.rb +191 -0
  85. data/lib/dynamoid/associations/single_association.rb +69 -0
  86. data/lib/dynamoid/components.rb +37 -0
  87. data/lib/dynamoid/config.rb +57 -0
  88. data/lib/dynamoid/config/options.rb +78 -0
  89. data/lib/dynamoid/criteria.rb +29 -0
  90. data/lib/dynamoid/criteria/chain.rb +326 -0
  91. data/lib/dynamoid/dirty.rb +47 -0
  92. data/lib/dynamoid/document.rb +199 -0
  93. data/lib/dynamoid/errors.rb +28 -0
  94. data/lib/dynamoid/fields.rb +138 -0
  95. data/lib/dynamoid/finders.rb +133 -0
  96. data/lib/dynamoid/identity_map.rb +96 -0
  97. data/lib/dynamoid/indexes.rb +69 -0
  98. data/lib/dynamoid/indexes/index.rb +103 -0
  99. data/lib/dynamoid/middleware/identity_map.rb +16 -0
  100. data/lib/dynamoid/persistence.rb +292 -0
  101. data/lib/dynamoid/validations.rb +36 -0
  102. data/spec/app/models/address.rb +13 -0
  103. data/spec/app/models/camel_case.rb +34 -0
  104. data/spec/app/models/car.rb +6 -0
  105. data/spec/app/models/magazine.rb +11 -0
  106. data/spec/app/models/message.rb +9 -0
  107. data/spec/app/models/nuclear_submarine.rb +5 -0
  108. data/spec/app/models/sponsor.rb +8 -0
  109. data/spec/app/models/subscription.rb +12 -0
  110. data/spec/app/models/tweet.rb +12 -0
  111. data/spec/app/models/user.rb +26 -0
  112. data/spec/app/models/vehicle.rb +7 -0
  113. data/spec/dynamoid/adapter/aws_sdk_spec.rb +376 -0
  114. data/spec/dynamoid/adapter_spec.rb +155 -0
  115. data/spec/dynamoid/associations/association_spec.rb +194 -0
  116. data/spec/dynamoid/associations/belongs_to_spec.rb +71 -0
  117. data/spec/dynamoid/associations/has_and_belongs_to_many_spec.rb +47 -0
  118. data/spec/dynamoid/associations/has_many_spec.rb +42 -0
  119. data/spec/dynamoid/associations/has_one_spec.rb +45 -0
  120. data/spec/dynamoid/associations_spec.rb +16 -0
  121. data/spec/dynamoid/config_spec.rb +27 -0
  122. data/spec/dynamoid/criteria/chain_spec.rb +210 -0
  123. data/spec/dynamoid/criteria_spec.rb +75 -0
  124. data/spec/dynamoid/dirty_spec.rb +57 -0
  125. data/spec/dynamoid/document_spec.rb +180 -0
  126. data/spec/dynamoid/fields_spec.rb +156 -0
  127. data/spec/dynamoid/finders_spec.rb +147 -0
  128. data/spec/dynamoid/identity_map_spec.rb +45 -0
  129. data/spec/dynamoid/indexes/index_spec.rb +104 -0
  130. data/spec/dynamoid/indexes_spec.rb +25 -0
  131. data/spec/dynamoid/persistence_spec.rb +301 -0
  132. data/spec/dynamoid/validations_spec.rb +36 -0
  133. data/spec/dynamoid_spec.rb +14 -0
  134. data/spec/spec_helper.rb +55 -0
  135. data/spec/support/with_partitioning.rb +15 -0
  136. metadata +363 -0
@@ -0,0 +1,180 @@
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, :deliverable => nil, :lock_version => 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, :deliverable => nil, :lock_version => 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, :deliverable => nil, :lock_version => 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
+ Address.exists?(:city => @address.city).should be_true
57
+ Address.exists?(:city => "does-not-exist").should be_false
58
+ end
59
+
60
+ it 'gets errors courtesy of ActiveModel' do
61
+ @address = Address.create(:city => 'Chicago')
62
+
63
+ @address.errors.should be_empty
64
+ @address.errors.full_messages.should be_empty
65
+ end
66
+
67
+ context '.reload' do
68
+ let(:address){ Address.create }
69
+ let(:message){ Message.create({:text => 'Nice, supporting datetime range!', :time => Time.now.to_datetime}) }
70
+ let(:tweet){ tweet = Tweet.create(:tweet_id => 'x', :group => 'abc') }
71
+
72
+ it 'reflects persisted changes' do
73
+ address.update_attributes(:city => 'Chicago')
74
+ address.reload.city.should == 'Chicago'
75
+ end
76
+
77
+ it 'uses a :consistent_read' do
78
+ Tweet.expects(:find).with(tweet.hash_key, {:range_key => tweet.range_value, :consistent_read => true}).returns(tweet)
79
+ tweet.reload
80
+ end
81
+
82
+ it 'works with range key' do
83
+ tweet.reload.group.should == 'abc'
84
+ end
85
+
86
+ it 'works with a :datetime range key' do
87
+ expect { message.reload }.to_not raise_error(ArgumentError)
88
+ end
89
+ end
90
+
91
+ it 'has default table options' do
92
+ @address = Address.create
93
+
94
+ @address.id.should_not be_nil
95
+ Address.table_name.should == 'dynamoid_tests_addresses'
96
+ Address.hash_key.should == :id
97
+ Address.read_capacity.should == 100
98
+ Address.write_capacity.should == 20
99
+ end
100
+
101
+ it 'follows any table options provided to it' do
102
+ @tweet = Tweet.create(:group => 12345)
103
+
104
+ lambda {@tweet.id}.should raise_error(NoMethodError)
105
+ @tweet.tweet_id.should_not be_nil
106
+ Tweet.table_name.should == 'dynamoid_tests_twitters'
107
+ Tweet.hash_key.should == :tweet_id
108
+ Tweet.read_capacity.should == 200
109
+ Tweet.write_capacity.should == 200
110
+ end
111
+
112
+ shared_examples 'it has equality testing and hashing' do
113
+ it 'is equal to itself' do
114
+ document.should == document
115
+ end
116
+
117
+ it 'is equal to another document with the same key(s)' do
118
+ document.should == same
119
+ end
120
+
121
+ it 'is not equal to another document with different key(s)' do
122
+ document.should_not == different
123
+ end
124
+
125
+ it 'is not equal to an object that is not a document' do
126
+ document.should_not == 'test'
127
+ end
128
+
129
+ it 'is not equal to nil' do
130
+ document.should_not == nil
131
+ end
132
+
133
+ it 'hashes documents with the keys to the same value' do
134
+ {document => 1}.should have_key(same)
135
+ end
136
+ end
137
+
138
+ context 'without a range key' do
139
+ it_behaves_like 'it has equality testing and hashing' do
140
+ let(:document) { Address.create(id: 123, city: 'Seattle') }
141
+ let(:different) { Address.create(id: 456, city: 'Seattle') }
142
+ let(:same) { Address.new(id: 123, city: 'Boston') }
143
+ end
144
+ end
145
+
146
+ context 'with a range key' do
147
+ it_behaves_like 'it has equality testing and hashing' do
148
+ let(:document){ Tweet.create(:tweet_id => 'x', :group => 'abc', :msg => 'foo') }
149
+ let(:different) { Tweet.create(:tweet_id => 'y', :group => 'abc', :msg => 'foo') }
150
+ let(:same) { Tweet.new(:tweet_id => 'x', :group => 'abc', :msg => 'bar') }
151
+ end
152
+
153
+ it 'is not equal to another document with the same hash key but a different range value' do
154
+ document = Tweet.create(:tweet_id => 'x', :group => 'abc')
155
+ different = Tweet.create(:tweet_id => 'x', :group => 'xyz')
156
+
157
+ document.should_not == different
158
+ end
159
+ end
160
+
161
+ context 'single table inheritance' do
162
+ it "should have a type" do
163
+ Vehicle.new.type.should == "Vehicle"
164
+ end
165
+
166
+ it "reports the same table name for both base and derived classes" do
167
+ Vehicle.table_name.should == Car.table_name
168
+ Vehicle.table_name.should == NuclearSubmarine.table_name
169
+ end
170
+ end
171
+
172
+ context '#count' do
173
+ it 'returns the number of documents in the table' do
174
+ document = Tweet.create(:tweet_id => 'x', :group => 'abc')
175
+ different = Tweet.create(:tweet_id => 'x', :group => 'xyz')
176
+
177
+ Tweet.count.should == 2
178
+ end
179
+ end
180
+ end
@@ -0,0 +1,156 @@
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(:deliverable => true)
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 'should update only created_at when no params are passed' do
79
+ @initial_updated_at = @address.updated_at
80
+ @address.update_attributes([])
81
+ @address.updated_at.should_not == @initial_updated_at
82
+ end
83
+
84
+ it 'adds in dirty methods for attributes' do
85
+ @address.city = 'Chicago'
86
+ @address.save
87
+
88
+ @address.city = 'San Francisco'
89
+
90
+ @address.city_was.should == 'Chicago'
91
+ end
92
+
93
+ it 'returns all attributes' do
94
+ Address.attributes.should == {:id=>{:type=>:string}, :created_at=>{:type=>:datetime}, :updated_at=>{:type=>:datetime}, :city=>{:type=>:string}, :options=>{:type=>:serialized}, :deliverable => {:type => :boolean}, :lock_version => {:type => :integer}}
95
+ end
96
+ end
97
+
98
+ it "gives a warning when setting a single value larger than the maximum item size" do
99
+ Dynamoid.logger.expects(:warn).with(regexp_matches(/city field has a length of 66000/))
100
+ Address.new city: ("Ten chars " * 6_600)
101
+ end
102
+
103
+ context '.remove_attribute' do
104
+ subject { @address }
105
+ before(:each) do
106
+ Address.field :foobar
107
+ Address.remove_field :foobar
108
+ end
109
+
110
+ it('should not be in the attributes hash') { Address.attributes.should_not have_key(:foobar) }
111
+ it('removes the accessor') { should_not respond_to(:foobar) }
112
+ it('removes the writer') { should_not respond_to(:foobar=) }
113
+ it('removes the interrogative') { should_not respond_to(:foobar?) }
114
+ end
115
+
116
+ context 'default values for fields' do
117
+ before do
118
+ @clazz = Class.new do
119
+ include Dynamoid::Document
120
+
121
+ field :name, :string, :default => 'x'
122
+ field :uid, :integer, :default => lambda { 42 }
123
+
124
+ def self.name
125
+ 'Document'
126
+ end
127
+ end
128
+
129
+
130
+ @doc = @clazz.new
131
+ end
132
+
133
+ it 'returns default value' do
134
+ @doc.name.should eq('x')
135
+ @doc.uid.should eq(42)
136
+ end
137
+
138
+ it 'should save default value' do
139
+ @doc.save!
140
+ @doc.reload.name.should eq('x')
141
+ @doc.uid.should eq(42)
142
+ end
143
+ end
144
+
145
+ context 'single table inheritance' do
146
+ it "has only base class fields on the base class" do
147
+ Vehicle.attributes.keys.to_set.should == Set.new([:type, :description, :created_at, :updated_at, :id])
148
+ end
149
+
150
+ it "has only the base and derived fields on a sub-class" do
151
+ #Only NuclearSubmarines have torpedoes
152
+ Car.attributes.should_not have_key(:torpedoes)
153
+ end
154
+ end
155
+
156
+ end
@@ -0,0 +1,147 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
2
+
3
+ describe "Dynamoid::Finders" do
4
+
5
+ before do
6
+ @address = Address.create(:city => 'Chicago')
7
+ end
8
+
9
+ it 'finds an existing address' do
10
+ found = Address.find(@address.id)
11
+
12
+ found.should == @address
13
+ found.city.should == 'Chicago'
14
+ end
15
+
16
+ it 'is not a new object' do
17
+ found = Address.find(@address.id)
18
+
19
+ found.new_record.should_not be_true
20
+ end
21
+
22
+ it 'returns nil when nothing is found' do
23
+ Address.find('1234').should be_nil
24
+ end
25
+
26
+ it 'finds multiple ids' do
27
+ @address2 = Address.create(:city => 'Illinois')
28
+
29
+ Address.find(@address.id, @address2.id).should include @address, @address2
30
+ end
31
+
32
+ it 'sends consistent option to the adapter' do
33
+ Dynamoid::Adapter.expects(:get_item).with { |table_name, key, options| options[:consistent_read] == true }
34
+ Address.find('x', :consistent_read => true)
35
+ end
36
+
37
+ context 'with users' do
38
+ before do
39
+ User.create_indexes
40
+ end
41
+
42
+ it 'finds using method_missing for attributes' do
43
+ array = Address.find_by_city('Chicago')
44
+
45
+ array.should == @address
46
+ end
47
+
48
+ it 'finds using method_missing for multiple attributes' do
49
+ @user = User.create(:name => 'Josh', :email => 'josh@joshsymonds.com')
50
+
51
+ array = User.find_all_by_name_and_email('Josh', 'josh@joshsymonds.com')
52
+
53
+ array.should == [@user]
54
+ end
55
+
56
+ it 'finds using method_missing for single attributes and multiple results' do
57
+ @user1 = User.create(:name => 'Josh', :email => 'josh@joshsymonds.com')
58
+ @user2 = User.create(:name => 'Josh', :email => 'josh@joshsymonds.com')
59
+
60
+ array = User.find_all_by_name('Josh')
61
+
62
+ array.size.should == 2
63
+ array.should include @user1
64
+ array.should include @user2
65
+ end
66
+
67
+ it 'finds using method_missing for multiple attributes and multiple results' do
68
+ @user1 = User.create(:name => 'Josh', :email => 'josh@joshsymonds.com')
69
+ @user2 = User.create(:name => 'Josh', :email => 'josh@joshsymonds.com')
70
+
71
+ array = User.find_all_by_name_and_email('Josh', 'josh@joshsymonds.com')
72
+
73
+ array.size.should == 2
74
+ array.should include @user1
75
+ array.should include @user2
76
+ end
77
+
78
+ it 'finds using method_missing for multiple attributes and no results' do
79
+ @user1 = User.create(:name => 'Josh', :email => 'josh@joshsymonds.com')
80
+ @user2 = User.create(:name => 'Justin', :email => 'justin@joshsymonds.com')
81
+
82
+ array = User.find_all_by_name_and_email('Gaga','josh@joshsymonds.com')
83
+
84
+ array.should be_empty
85
+ end
86
+
87
+ it 'finds using method_missing for a single attribute and no results' do
88
+ @user1 = User.create(:name => 'Josh', :email => 'josh@joshsymonds.com')
89
+ @user2 = User.create(:name => 'Justin', :email => 'justin@joshsymonds.com')
90
+
91
+ array = User.find_all_by_name('Gaga')
92
+
93
+ array.should be_empty
94
+ end
95
+
96
+ it 'should find on a query that is not indexed' do
97
+ @user = User.create(:password => 'Test')
98
+
99
+ array = User.find_all_by_password('Test')
100
+
101
+ array.should == [@user]
102
+ end
103
+
104
+ it 'should find on a query on multiple attributes that are not indexed' do
105
+ @user = User.create(:password => 'Test', :name => 'Josh')
106
+
107
+ array = User.find_all_by_password_and_name('Test', 'Josh')
108
+
109
+ array.should == [@user]
110
+ end
111
+
112
+ it 'should return an empty array when fields exist but nothing is found' do
113
+ array = User.find_all_by_password('Test')
114
+
115
+ array.should be_empty
116
+ end
117
+
118
+ end
119
+
120
+ context 'find_all' do
121
+
122
+ it 'should return a array of users' do
123
+ users = (1..10).map { User.create }
124
+ User.find_all(users.map(&:id)).should eq(users)
125
+ end
126
+
127
+ it 'should return a array of tweets' do
128
+ tweets = (1..10).map { |i| Tweet.create(:tweet_id => "#{i}", :group => "group_#{i}") }
129
+ Tweet.find_all(tweets.map { |t| [t.tweet_id, t.group] }).should eq(tweets)
130
+ end
131
+
132
+ it 'should return an empty array' do
133
+ User.find_all([]).should eq([])
134
+ end
135
+
136
+ it 'returns empty array when there are no results' do
137
+ Address.find_all('bad' + @address.id.to_s).should eq []
138
+ end
139
+
140
+ it 'passes options to the adapter' do
141
+ user_ids = [%w(1 red), %w(1 green)]
142
+ Dynamoid::Adapter.expects(:read).with(anything, user_ids, :consistent_read => true)
143
+ User.find_all(user_ids, :consistent_read => true)
144
+ end
145
+
146
+ end
147
+ end