dynamini 1.8.2 → 1.9.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.
@@ -0,0 +1,77 @@
1
+ require 'spec_helper'
2
+
3
+ describe Dynamini::BatchOperations do
4
+
5
+ let(:model_attributes) {
6
+ {
7
+ name: 'Widget',
8
+ price: 9.99,
9
+ id: 'abcd1234',
10
+ hash_key: '009'
11
+ }
12
+ }
13
+
14
+ let(:model) { Dynamini::Base.new(model_attributes) }
15
+
16
+ subject { Dynamini::Base }
17
+
18
+ describe '.import' do
19
+ it 'should generate timestamps for each model' do
20
+ model1 = Dynamini::Base.new(model_attributes)
21
+ model2 = Dynamini::Base.new(model_attributes.merge(id: '2'))
22
+
23
+ subject.import([model1, model2])
24
+
25
+ expect(subject.find(model1.id).updated_at).not_to be_nil
26
+ expect(subject.find(model1.id).created_at).not_to be_nil
27
+ expect(subject.find(model2.id).updated_at).not_to be_nil
28
+ expect(subject.find(model2.id).created_at).not_to be_nil
29
+ end
30
+
31
+ it 'should call .dynamo_batch_save with batches of 25 models' do
32
+ models = Array.new(30, model)
33
+ expect(subject).to receive(:dynamo_batch_save).with(array_including(models[0..24])).ordered
34
+ expect(subject).to receive(:dynamo_batch_save).with(array_including(models[25..29])).ordered
35
+ subject.import(models)
36
+ end
37
+ end
38
+
39
+ describe '.dynamo_batch_save' do
40
+ it 'should batch write the models to dynamo' do
41
+ model2 = Dynamini::Base.new(id: '123')
42
+ model3 = Dynamini::Base.new(id: '456')
43
+ Dynamini::Base.dynamo_batch_save([model2, model3])
44
+ expect(Dynamini::Base.find('123')).to_not be_nil
45
+ expect(Dynamini::Base.find('456')).to_not be_nil
46
+ end
47
+ end
48
+
49
+ describe '.batch_find' do
50
+ before do
51
+ model.save
52
+ end
53
+ context 'when requesting 0 items' do
54
+ it 'should return an empty array' do
55
+ expect(Dynamini::Base.batch_find).to eq []
56
+ end
57
+ end
58
+ context 'when requesting 2 items' do
59
+ it 'should return a 2-length array containing each item' do
60
+ Dynamini::Base.create(id: '4321')
61
+ objects = Dynamini::Base.batch_find(['abcd1234', '4321'])
62
+ expect(objects.length).to eq 2
63
+ expect(objects.first.id).to eq model.id
64
+ expect(objects.last.id).to eq '4321'
65
+ end
66
+ end
67
+ context 'when requesting too many items' do
68
+ it 'should raise an error' do
69
+ a = []
70
+ 150.times { a << 'foo' }
71
+ expect { Dynamini::Base.batch_find(a) }.to raise_error StandardError
72
+ end
73
+ end
74
+ end
75
+
76
+ end
77
+
@@ -0,0 +1,187 @@
1
+ require 'spec_helper'
2
+
3
+ describe Dynamini::TestClient do
4
+
5
+ let(:table_name) { 'table' }
6
+
7
+ describe '#update_item' do
8
+
9
+ context 'with hash key ONLY' do
10
+ it 'should be able to save a record' do
11
+ test_client = Dynamini::TestClient.new(:hash_key_name)
12
+ test_client.update_item(table_name: table_name, key: {hash_key_name: 'hash_key_value'}, attribute_updates: {abc: {value: 'abc', action: 'PUT'}})
13
+ expect(test_client.data[table_name]['hash_key_value']).to eq(abc: 'abc', :hash_key_name => "hash_key_value")
14
+ end
15
+
16
+ it 'should be able to update an existing record' do
17
+ test_client = Dynamini::TestClient.new(:hash_key_name)
18
+ test_client.update_item(table_name: table_name, key: {hash_key_name: 'hash_key_value'}, attribute_updates: {abc: {value: 'abc', action: 'PUT'}})
19
+ test_client.update_item(table_name: table_name, key: {hash_key_name: 'hash_key_value'}, attribute_updates: {abc: {value: 'def', action: 'PUT'}})
20
+ expect(test_client.data[table_name]['hash_key_value']).to eq(abc: 'def', :hash_key_name => "hash_key_value")
21
+ end
22
+
23
+ end
24
+
25
+ context 'with Hash key and range key' do
26
+ it 'should be able to save a record' do
27
+ test_client = Dynamini::TestClient.new(:hash_key_name, :range_key_name)
28
+ test_client.update_item(table_name: table_name, key: {hash_key_name: 'hash_key_value', range_key_name: 'range_key_value'}, attribute_updates: {abc: {value: 'abc', action: 'PUT'}})
29
+ expect(test_client.data[table_name]['hash_key_value']['range_key_value']).to eq({abc: 'abc', :hash_key_name => "hash_key_value", :range_key_name => "range_key_value"})
30
+ end
31
+
32
+ it 'should update an existing record' do
33
+ test_client = Dynamini::TestClient.new(:hash_key_name, :range_key_name)
34
+ test_client.update_item(table_name: table_name, key: {hash_key_name: 'hash_key_value', range_key_name: 'range_key_value'}, attribute_updates: {abc: {value: 'abc', action: 'PUT'}})
35
+
36
+ test_client.update_item(table_name: table_name, key: {hash_key_name: 'hash_key_value', range_key_name: 'range_key_value'}, attribute_updates: {abc: {value: 'def', action: 'PUT'}})
37
+
38
+ expect(test_client.data[table_name]['hash_key_value']['range_key_value']).to eq({abc: 'def', :hash_key_name => "hash_key_value", :range_key_name => "range_key_value"})
39
+ end
40
+
41
+ end
42
+
43
+ context 'invalid args' do
44
+ it 'should not try to add invalid args for a hash key only table' do
45
+ test_client = Dynamini::TestClient.new(:hash_key_name)
46
+ test_client.update_item(table_name: table_name, key: {}, attribute_updates: {abc: {value: 'def', action: 'PUT'}})
47
+
48
+ expect(test_client.data[table_name]).to eq({})
49
+ end
50
+
51
+ it 'should not try to add invalid args for a hash key and range key table' do
52
+ test_client = Dynamini::TestClient.new(:hash_key_name, :range_key_name)
53
+ test_client.update_item(table_name: table_name, key: {}, attribute_updates: {abc: {value: 'def', action: 'PUT'}})
54
+
55
+ expect(test_client.data[table_name]).to eq({})
56
+ end
57
+ end
58
+ end
59
+
60
+ describe '#get_item' do
61
+ context 'table with just a hash key' do
62
+ let(:test_client) { Dynamini::TestClient.new(:hash_key_name) }
63
+
64
+ it 'should return the item identified by the hash_key' do
65
+ test_client.update_item(table_name: table_name, key: {test_client.hash_key_attr => "abc"}, attribute_updates: {test_attr: {value: 'test', action: 'PUT'}})
66
+
67
+ expect(test_client.get_item(table_name: table_name, key: {test_client.hash_key_attr => "abc"}).item[:test_attr]).to eq('test')
68
+ end
69
+
70
+ it 'should returns nil if the item does not exist' do
71
+ expect(test_client.get_item(table_name: table_name, key: {test_client.hash_key_attr => "abc"}).item).to eq(nil)
72
+ end
73
+
74
+ it 'should ignore any extra keys in the args' do
75
+ test_client.update_item(table_name: table_name, key: {test_client.hash_key_attr => "abc"}, attribute_updates: {test_attr: {value: 'test', action: 'PUT'}})
76
+
77
+ expect(test_client.get_item(table_name: table_name, key: {test_client.hash_key_attr => "abc", :extra_key => "extra"}).item[:test_attr]).to eq('test')
78
+ end
79
+ end
80
+
81
+ context 'table with hash and range key' do
82
+ let(:test_client) { Dynamini::TestClient.new(:hash_key_name, :range_key_name) }
83
+
84
+ it 'should return the item identified by the hash_key' do
85
+ test_client.update_item(table_name: table_name, key: {test_client.hash_key_attr => "abc", test_client.range_key_attr => 'def'}, attribute_updates: {test_attr: {value: 'test_range', action: 'PUT'}})
86
+
87
+ expect(test_client.get_item(table_name: table_name, key: {test_client.hash_key_attr => "abc", test_client.range_key_attr => 'def'}).item[:test_attr]).to eq('test_range')
88
+ end
89
+
90
+ it 'should returns nil if the item does not exist' do
91
+ expect(test_client.get_item(table_name: table_name, key: {test_client.hash_key_attr => "abc", test_client.range_key_attr => 'def'}).item).to eq(nil)
92
+ end
93
+
94
+ it 'should return nil when only supplied range key' do
95
+ expect(test_client.get_item(table_name: table_name, key: {test_client.range_key_attr => 'def'}).item).to eq(nil)
96
+ end
97
+ end
98
+ end
99
+
100
+ describe '#query' do
101
+
102
+ let(:test_client) { Dynamini::TestClient.new(:hash_key_field, :range_key_field) }
103
+
104
+ before do
105
+ 4.times do |i|
106
+ test_client.update_item(table_name: table_name, key: {hash_key_field: 'foo', range_key_field: i + 1}, attribute_updates: {abc: {value: 'abc', action: 'PUT'}})
107
+ end
108
+ end
109
+ context 'with LE operator' do
110
+ it 'should return all items with range key less than or equal to the provided value' do
111
+ response = test_client.query(
112
+ table_name: table_name,
113
+ key_condition_expression: "hash_key_field = :h AND user_id <= :e",
114
+ expression_attribute_values: {
115
+ ":h" => 'foo',
116
+ ":e" => 2
117
+ }
118
+ )
119
+ expect(response.items.length).to eq(2)
120
+ expect(response.items.first[:range_key_field]).to eq(1)
121
+ expect(response.items.last[:range_key_field]).to eq(2)
122
+ end
123
+ end
124
+ context 'with GE operator' do
125
+ it 'should return all items with range key greater than or equal to the provided value' do
126
+ response = test_client.query(
127
+ table_name: table_name,
128
+ key_condition_expression: "hash_key_field = :h AND user_id >= :s",
129
+ expression_attribute_values: {
130
+ ":h" => 'foo',
131
+ ":s" => 2
132
+ }
133
+ )
134
+ expect(response.items.length).to eq(3)
135
+ expect(response.items.first[:range_key_field]).to eq(2)
136
+ expect(response.items.last[:range_key_field]).to eq(4)
137
+ end
138
+ end
139
+ context 'with BETWEEN operator' do
140
+ it 'should return all items with range key between the provided values' do
141
+ response = test_client.query(
142
+ table_name: table_name,
143
+ key_condition_expression: "hash_key_field = :h AND user_id BETWEEN :s AND :e",
144
+ expression_attribute_values: {
145
+ ":h" => 'foo',
146
+ ":s" => 2,
147
+ ":e" => 3
148
+ }
149
+ )
150
+ expect(response.items.length).to eq(2)
151
+ expect(response.items.first[:range_key_field]).to eq(2)
152
+ expect(response.items.last[:range_key_field]).to eq(3)
153
+ end
154
+ end
155
+ context 'with no operator' do
156
+ it 'should return all items with range key between the provided values' do
157
+ response = test_client.query(
158
+ table_name: table_name,
159
+ key_condition_expression: "hash_key_field = :h",
160
+ expression_attribute_values: {
161
+ ":h" => 'foo'
162
+ }
163
+ )
164
+ expect(response.items.length).to eq(4)
165
+ expect(response.items.first[:range_key_field]).to eq(1)
166
+ expect(response.items.last[:range_key_field]).to eq(4)
167
+ end
168
+ end
169
+ end
170
+
171
+ describe '#batch_write_item' do
172
+ let(:test_client) { Dynamini::TestClient.new(:id) }
173
+
174
+ it 'should store all items in the table correctly' do
175
+ item1 = {'foo' => 'bar', 'id' => 1}
176
+ item2 = {'foo' => 'bar', 'id' => 2}
177
+ put_requests = [{put_request: {item: item1}},
178
+ {put_request: {item: item2}}]
179
+
180
+ request_options = {request_items: {table_name => put_requests}}
181
+
182
+ test_client.batch_write_item(request_options)
183
+ expect(test_client.data[table_name][1]).to eq(item1)
184
+ expect(test_client.data[table_name][2]).to eq(item2)
185
+ end
186
+ end
187
+ end
@@ -0,0 +1,15 @@
1
+ require 'bundler/setup'
2
+ Bundler.setup
3
+
4
+ require 'aws-sdk'
5
+ require 'pry'
6
+ require 'fuubar'
7
+ require 'dynamini'
8
+
9
+ RSpec.configure do |config|
10
+ # For running just wanted tests in guard
11
+ config.filter_run :focus => true
12
+ config.run_all_when_everything_filtered = true
13
+ config.before(:all) { Dynamini::Base.in_memory = true }
14
+ config.after(:each) { Dynamini::Base.client.reset }
15
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: dynamini
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.8.2
4
+ version: 1.9.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Greg Ward
@@ -130,10 +130,26 @@ executables: []
130
130
  extensions: []
131
131
  extra_rdoc_files: []
132
132
  files:
133
+ - .gitignore
134
+ - .rspec
135
+ - .travis.yml
136
+ - Gemfile
137
+ - Gemfile.lock
138
+ - Guardfile
139
+ - LICENSE
140
+ - README.md
141
+ - Rakefile
142
+ - dynamini.gemspec
143
+ - lib/.DS_Store
133
144
  - lib/dynamini.rb
134
145
  - lib/dynamini/base.rb
146
+ - lib/dynamini/batch_operations.rb
135
147
  - lib/dynamini/configuration.rb
136
148
  - lib/dynamini/test_client.rb
149
+ - spec/dynamini/base_spec.rb
150
+ - spec/dynamini/batch_operations_spec.rb
151
+ - spec/dynamini/test_client_spec.rb
152
+ - spec/spec_helper.rb
137
153
  homepage: https://github.com/47colborne/dynamini
138
154
  licenses:
139
155
  - MIT
@@ -154,8 +170,12 @@ required_rubygems_version: !ruby/object:Gem::Requirement
154
170
  version: '0'
155
171
  requirements: []
156
172
  rubyforge_project:
157
- rubygems_version: 2.4.8
173
+ rubygems_version: 2.2.2
158
174
  signing_key:
159
175
  specification_version: 4
160
176
  summary: DynamoDB interface
161
- test_files: []
177
+ test_files:
178
+ - spec/dynamini/base_spec.rb
179
+ - spec/dynamini/batch_operations_spec.rb
180
+ - spec/dynamini/test_client_spec.rb
181
+ - spec/spec_helper.rb