dynamini 1.10.1 → 1.10.2

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 7ac958908500fd7c64b8c6476a6bac8e20c09966
4
- data.tar.gz: 48552250242ac4617aae6f21151a90fb2baa5382
3
+ metadata.gz: 8248aff788be3cda0502be12ccc3768cdf4fc3d4
4
+ data.tar.gz: 860898330266f91bce5a52d1a4193edce7f64e07
5
5
  SHA512:
6
- metadata.gz: ac7bd1db86987a5555a33d4958988635e20c005fd9d04e8e8480838b4b90ce6b6fdea4212321b6b83b467be2c970f8db305a9697d5f59d5b2e47eda890a3d141
7
- data.tar.gz: 50a9a0a883421c0fc8903eba5f377c71cc4757556acf4af7e3d7e03b10d346b67c2a59962b30e2de22f7cbe072f43107cdeb2665184a87c29a65ec7ca6f66573
6
+ metadata.gz: 9dc5d37aefc854902b172a271a2b80b5ab22310f507ad2f5c234a60bb81d00b5a2f0a69bdd2ef8fe6c426830fe06d9f985f67d51db62b83a98d4eb8d6a956bee
7
+ data.tar.gz: 9efb1fd623f05c5eba81660ea04e46873d222634b5aca361b69205e75eccb1ad2c1fef2d53cf44555514eb5eae68aa559aec1ddebdc2a03dd53a49219a6c86ad
data/Gemfile.lock CHANGED
@@ -1,17 +1,17 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- dynamini (1.10.1)
4
+ dynamini (1.10.2)
5
5
  activemodel (>= 3, < 5.0)
6
6
  aws-sdk (~> 2)
7
7
 
8
8
  GEM
9
9
  remote: https://rubygems.org/
10
10
  specs:
11
- activemodel (4.2.4)
12
- activesupport (= 4.2.4)
11
+ activemodel (4.2.5)
12
+ activesupport (= 4.2.5)
13
13
  builder (~> 3.1)
14
- activesupport (4.2.4)
14
+ activesupport (4.2.5)
15
15
  i18n (~> 0.7)
16
16
  json (~> 1.7, >= 1.7.7)
17
17
  minitest (~> 5.1)
@@ -56,7 +56,7 @@ GEM
56
56
  rb-inotify (>= 0.9)
57
57
  lumberjack (1.0.9)
58
58
  method_source (0.8.2)
59
- minitest (5.8.2)
59
+ minitest (5.8.3)
60
60
  nenv (0.2.0)
61
61
  notiffany (0.0.8)
62
62
  nenv (~> 0.1)
data/dynamini.gemspec CHANGED
@@ -1,6 +1,6 @@
1
1
  Gem::Specification.new do |s|
2
2
  s.name = 'dynamini'
3
- s.version = '1.10.1'
3
+ s.version = '1.10.2'
4
4
  s.date = '2015-01-07'
5
5
  s.summary = 'DynamoDB interface'
6
6
  s.description = 'Lightweight DynamoDB interface gem designed as
data/lib/dynamini/base.rb CHANGED
@@ -1,10 +1,12 @@
1
1
  require_relative 'batch_operations'
2
+ require_relative 'querying'
2
3
 
3
4
  module Dynamini
4
5
  # Core db interface class.
5
6
  class Base
6
7
  include ActiveModel::Validations
7
8
  extend Dynamini::BatchOperations
9
+ extend Dynamini::Querying
8
10
 
9
11
  attr_reader :attributes
10
12
 
@@ -91,45 +93,6 @@ module Dynamini
91
93
  model = new(attributes, true)
92
94
  model if model.save!(options)
93
95
  end
94
-
95
- def find(hash_value, range_value = nil)
96
- fail 'Range key cannot be blank.' if range_key && range_value.nil?
97
- response = client.get_item(table_name: table_name, key: create_key_hash(hash_value, range_value))
98
- raise 'Item not found.' unless response.item
99
- new(response.item.symbolize_keys, false)
100
- end
101
-
102
- def exists?(hash_value, range_value = nil)
103
- fail 'Range key cannot be blank.' if range_key && range_value.nil?
104
-
105
- r = client.get_item(table_name: table_name, key: create_key_hash(hash_value, range_value))
106
- r.item.present?
107
- end
108
-
109
- def find_or_new(hash_value, range_value = nil)
110
- fail 'Key cannot be blank.' if (hash_value.nil? || hash_value == '')
111
- fail 'Range key cannot be blank.' if range_key && range_value.nil?
112
-
113
- r = client.get_item(table_name: table_name, key: create_key_hash(hash_value, range_value))
114
- if r.item
115
- new(r.item.symbolize_keys, false)
116
- else
117
- range_key ? new(hash_key => hash_value, range_key => range_value) : new(hash_key => hash_value)
118
- end
119
- end
120
-
121
- def query(args = {})
122
- fail ArgumentError, 'You must provide a :hash_key.' unless args[:hash_key]
123
- fail TypeError, 'Your range key must be handled as an integer, float, date, or time.' unless self.range_is_numeric?
124
-
125
- response = self.dynamo_query(args)
126
- objects = []
127
- response.items.each do |item|
128
- objects << new(item.symbolize_keys, false)
129
- end
130
- objects
131
- end
132
-
133
96
  end
134
97
 
135
98
  #### Instance Methods
@@ -273,37 +236,6 @@ module Dynamini
273
236
  )
274
237
  end
275
238
 
276
- def self.dynamo_query(args)
277
- expression_attribute_values = self.build_expression_attribute_values(args)
278
- key_condition_expression = self.build_key_condition_expression(args)
279
-
280
- client.query(
281
- table_name: table_name,
282
- key_condition_expression: key_condition_expression,
283
- expression_attribute_values: expression_attribute_values
284
- )
285
- end
286
-
287
- def self.build_expression_attribute_values(args)
288
- expression_values = {}
289
- expression_values[':h'] = args[:hash_key]
290
- expression_values[':s'] = args[:start] if args[:start]
291
- expression_values[':e'] = args[:end] if args[:end]
292
- expression_values
293
- end
294
-
295
- def self.build_key_condition_expression(args)
296
- expression = "#{hash_key} = :h"
297
- if args[:start] && args[:end]
298
- expression += " AND #{range_key} BETWEEN :s AND :e"
299
- elsif args[:start]
300
- expression += " AND #{range_key} >= :s"
301
- elsif args[:end]
302
- expression += " AND #{range_key} <= :e"
303
- end
304
- expression
305
- end
306
-
307
239
  def key
308
240
  key_hash = { self.class.hash_key => @attributes[self.class.hash_key] }
309
241
  key_hash[self.class.range_key] = @attributes[self.class.range_key] if self.class.range_key
@@ -316,30 +248,6 @@ module Dynamini
316
248
  key_hash
317
249
  end
318
250
 
319
- def self.build_range_expression(start_value, end_value)
320
- operator = (
321
- if start_value && end_value
322
- 'BETWEEN'
323
- elsif start_value
324
- 'GE'
325
- elsif end_value
326
- 'LE'
327
- end
328
- )
329
- attribute_value_list = []
330
-
331
- if handle = handles[range_key.to_sym]
332
- attribute_value_list << attribute_callback(SETTER_PROCS, handle, start_value) if start_value
333
- attribute_value_list << attribute_callback(SETTER_PROCS, handle, end_value) if end_value
334
- else
335
- attribute_value_list << start_value if start_value
336
- attribute_value_list << end_value if end_value
337
- end
338
-
339
- {attribute_value_list: attribute_value_list, comparison_operator: operator}
340
- end
341
-
342
-
343
251
  def attribute_updates
344
252
  changes.reduce({}) do |updates, (key, value)|
345
253
  current_value = value[1]
@@ -0,0 +1,101 @@
1
+ module Dynamini
2
+ module Querying
3
+
4
+ def find(hash_value, range_value = nil)
5
+ fail 'Range key cannot be blank.' if range_key && range_value.nil?
6
+ response = client.get_item(table_name: table_name, key: create_key_hash(hash_value, range_value))
7
+ raise 'Item not found.' unless response.item
8
+ new(response.item.symbolize_keys, false)
9
+ end
10
+
11
+ def exists?(hash_value, range_value = nil)
12
+ fail 'Range key cannot be blank.' if range_key && range_value.nil?
13
+
14
+ r = client.get_item(table_name: table_name, key: create_key_hash(hash_value, range_value))
15
+ r.item.present?
16
+ end
17
+
18
+ def find_or_new(hash_value, range_value = nil)
19
+ fail 'Key cannot be blank.' if (hash_value.nil? || hash_value == '')
20
+ fail 'Range key cannot be blank.' if range_key && range_value.nil?
21
+
22
+ r = client.get_item(table_name: table_name, key: create_key_hash(hash_value, range_value))
23
+ if r.item
24
+ new(r.item.symbolize_keys, false)
25
+ else
26
+ range_key ? new(hash_key => hash_value, range_key => range_value) : new(hash_key => hash_value)
27
+ end
28
+ end
29
+
30
+ def query(args = {})
31
+ fail ArgumentError, 'You must provide a :hash_key.' unless args[:hash_key]
32
+ fail TypeError, 'Your range key must be handled as an integer, float, date, or time.' unless self.range_is_numeric?
33
+
34
+ response = dynamo_query(args)
35
+ objects = []
36
+ response.items.each do |item|
37
+ objects << new(item.symbolize_keys, false)
38
+ end
39
+ objects
40
+ end
41
+
42
+ private
43
+
44
+ def dynamo_query(args)
45
+ expression_attribute_values = build_expression_attribute_values(args)
46
+ key_condition_expression = build_key_condition_expression(args)
47
+
48
+ client.query(
49
+ table_name: table_name,
50
+ key_condition_expression: key_condition_expression,
51
+ expression_attribute_values: expression_attribute_values
52
+ )
53
+ end
54
+
55
+ def build_expression_attribute_values(args)
56
+ expression_values = {}
57
+ expression_values[':h'] = args[:hash_key]
58
+ expression_values[':s'] = args[:start] if args[:start]
59
+ expression_values[':e'] = args[:end] if args[:end]
60
+ expression_values
61
+ end
62
+
63
+ def build_key_condition_expression(args)
64
+ expression = "#{hash_key} = :h"
65
+ if args[:start] && args[:end]
66
+ expression += " AND #{range_key} BETWEEN :s AND :e"
67
+ elsif args[:start]
68
+ expression += " AND #{range_key} >= :s"
69
+ elsif args[:end]
70
+ expression += " AND #{range_key} <= :e"
71
+ end
72
+ expression
73
+ end
74
+
75
+ #FIXME unused method
76
+ def build_range_expression(start_value, end_value)
77
+ operator = (
78
+ if start_value && end_value
79
+ 'BETWEEN'
80
+ elsif start_value
81
+ 'GE'
82
+ elsif end_value
83
+ 'LE'
84
+ end
85
+ )
86
+ attribute_value_list = []
87
+
88
+ if handle = handles[range_key.to_sym]
89
+ attribute_value_list << attribute_callback(SETTER_PROCS, handle, start_value) if start_value
90
+ attribute_value_list << attribute_callback(SETTER_PROCS, handle, end_value) if end_value
91
+ else
92
+ attribute_value_list << start_value if start_value
93
+ attribute_value_list << end_value if end_value
94
+ end
95
+
96
+ {attribute_value_list: attribute_value_list, comparison_operator: operator}
97
+ end
98
+
99
+
100
+ end
101
+ end
@@ -65,11 +65,11 @@ module Dynamini
65
65
  def batch_get_item(args = {})
66
66
  responses = {}
67
67
 
68
- args[:request_items].each do |k, v|
69
- responses[k] = []
70
- v[:keys].each do |key_hash|
71
- item = @data[k][key_hash.values.first]
72
- responses[k] << item unless item.nil?
68
+ args[:request_items].each do |table_name, get_request|
69
+ responses[table_name] = []
70
+ get_request[:keys].each do |key_hash|
71
+ item = get_table(table_name)[key_hash.values.first]
72
+ responses[table_name] << item unless item.nil?
73
73
  end
74
74
  end
75
75
 
@@ -78,18 +78,17 @@ module Dynamini
78
78
 
79
79
  #FIXME Add range key support
80
80
  def batch_write_item(request_options)
81
- request_options[:request_items].each do |k, v|
82
- @data[k] ||= {}
83
- v.each do |request_hash|
81
+ request_options[:request_items].each do |table_name, put_requests|
82
+ put_requests.each do |request_hash|
84
83
  item = request_hash[:put_request][:item]
85
84
  key = item[hash_key_attr.to_s]
86
- @data[k][key] = item
85
+ get_table(table_name)[key] = item
87
86
  end
88
87
  end
89
88
  end
90
89
 
91
90
  def delete_item(args = {})
92
- @data[args[:table_name]].delete(args[:key][hash_key_attr])
91
+ get_table(args[:table_name]).delete(args[:key][hash_key_attr])
93
92
  end
94
93
 
95
94
  def query(args = {})
@@ -119,7 +118,7 @@ module Dynamini
119
118
  start_val = nil
120
119
  end_val = nil
121
120
  end
122
- parent = @data[args[:table_name]][hash_key]
121
+ parent = get_table(args[:table_name])[hash_key]
123
122
  return OpenStruct.new(items:[]) unless parent
124
123
 
125
124
  selected = parent.values
@@ -143,10 +142,11 @@ module Dynamini
143
142
 
144
143
  if args[:attribute_updates]
145
144
  args[:attribute_updates].each do |k, v|
145
+ table = get_table(args[:table_name])
146
146
 
147
- if v[:action] == 'ADD' && @data[args[:table_name]][hash_key_value]
147
+ if v[:action] == 'ADD' && table[hash_key_value]
148
148
  # if record has been saved
149
- data = @data[args[:table_name]][hash_key_value]
149
+ data = table[hash_key_value]
150
150
  data = (data[range_key_value] ||= {}) if range_key_value
151
151
 
152
152
  attribute_hash[k] = (v[:value] + data[k].to_f)
@@ -119,91 +119,6 @@ describe Dynamini::Base do
119
119
  end
120
120
  end
121
121
 
122
- describe '.find' do
123
-
124
- it 'should return a model with the retrieved attributes' do
125
- found = Dynamini::Base.find('abcd1234')
126
- expect(found.price).to eq(9.99)
127
- expect(found.name).to eq('Widget')
128
- expect(found.hash_key).to eq('009')
129
- end
130
-
131
- context 'when the object does not exist' do
132
- it 'should raise an error' do
133
- expect { Dynamini::Base.find('f') }.to raise_error 'Item not found.'
134
- end
135
-
136
- end
137
-
138
- context 'when retrieving a subclass' do
139
- class Foo < Dynamini::Base
140
- self.in_memory = true
141
- end
142
-
143
- it 'should return the object as an instance of the subclass' do
144
- Foo.create(id: '1')
145
- expect(Foo.find('1')).to be_a Foo
146
- end
147
- end
148
- end
149
-
150
- describe '.query' do
151
- before do
152
- 4.times do |i|
153
- TestClassWithRange.create(foo: 'foo', bar: i + 1)
154
- end
155
- end
156
- context 'start value provided' do
157
- it 'should return records with a range key greater than or equal to the start value' do
158
- records = TestClassWithRange.query(hash_key: 'foo', start: 2)
159
- expect(records.length).to eq 3
160
- expect(records.first.bar).to eq 2
161
- expect(records.last.bar).to eq 4
162
- end
163
- end
164
- context 'end value provided' do
165
- it 'should return records with a range key less than or equal to the start value' do
166
- records = TestClassWithRange.query(hash_key: 'foo', end: 2)
167
- expect(records.length).to eq 2
168
- expect(records.first.bar).to eq 1
169
- expect(records.last.bar).to eq 2
170
- end
171
- end
172
- context 'start and end values provided' do
173
- it 'should return records between the two values inclusive' do
174
- records = TestClassWithRange.query(hash_key: 'foo', start: 1, end: 3)
175
- expect(records.length).to eq 3
176
- expect(records.first.bar).to eq 1
177
- expect(records.last.bar).to eq 3
178
- end
179
- end
180
- context 'neither value provided' do
181
- it 'should return all records belonging to that hash key' do
182
- records = TestClassWithRange.query(hash_key: 'foo')
183
- expect(records.length).to eq 4
184
- expect(records.first.bar).to eq 1
185
- expect(records.last.bar).to eq 4
186
- end
187
- end
188
-
189
- context 'a non-numeric range field' do
190
- it 'should raise an error' do
191
- class TestClassWithStringRange < Dynamini::Base
192
- self.in_memory = true
193
- set_hash_key :group
194
- set_range_key :user_name
195
- end
196
- expect { TestClassWithStringRange.query(hash_key: 'registered', start: 'a') }.to raise_error TypeError
197
- end
198
- end
199
-
200
- context 'hash key does not exist' do
201
- it 'should return an empty array' do
202
- expect(TestClassWithRange.query(hash_key: 'non-existent key')).to eq([])
203
- end
204
- end
205
- end
206
-
207
122
  describe '.increment!' do
208
123
  context 'when incrementing a nil value' do
209
124
  it 'should save' do
@@ -277,36 +192,6 @@ describe Dynamini::Base do
277
192
  end
278
193
  end
279
194
 
280
- describe '.find_or_new' do
281
- context 'when a record with the given key exists' do
282
- it 'should return that record' do
283
- existing_record = Dynamini::Base.find_or_new(model.id)
284
- expect(existing_record.new_record?).to eq(false)
285
- expect(existing_record.id).to eq(model.id)
286
- end
287
-
288
- it 'should return the record for table with range key' do
289
- existing_record = TestClassWithRange.create!(foo: 1, bar: 123)
290
- expect(TestClassWithRange.find_or_new(existing_record.foo, existing_record.bar).new_record?).to eq(false)
291
- expect(existing_record.foo).to eq(1)
292
- expect(existing_record.bar).to eq(123)
293
- end
294
-
295
- end
296
- context 'when the key cannot be found' do
297
- it 'should initialize a new object with that key' do
298
- expect(Dynamini::Base.find_or_new('foo').new_record?).to be_truthy
299
- end
300
-
301
- it 'should initialize a new object with hash key and range key' do
302
- new_record = TestClassWithRange.find_or_new(1, 6)
303
- expect(new_record.new_record?).to be_truthy
304
- expect(new_record.foo).to eq(1)
305
- expect(new_record.bar).to eq(6)
306
- end
307
- end
308
- end
309
-
310
195
  describe '#==' do
311
196
  let(:model_a) { Dynamini::Base.new(model_attributes).tap {
312
197
  |model| model.send(:clear_changes)
@@ -672,40 +557,6 @@ describe Dynamini::Base do
672
557
  end
673
558
  end
674
559
 
675
- describe '.exists?' do
676
-
677
- context 'with hash key' do
678
- context 'the item exists' do
679
- it 'should return true' do
680
- expect(Dynamini::Base.exists?(model_attributes[:id])).to be_truthy
681
- end
682
- end
683
-
684
- context 'the item does not exist' do
685
- it 'should return false' do
686
- expect(Dynamini::Base.exists?('nonexistent id')).to eq(false)
687
- end
688
- end
689
- end
690
-
691
- context 'with hash key and range key' do
692
-
693
- it 'should return true if item exists' do
694
- TestClassWithRange.create!(foo: 'abc', bar: 123)
695
-
696
- expect(TestClassWithRange.exists?('abc', 123)).to eq(true)
697
- end
698
-
699
- it 'should return false if the item does not exist' do
700
- TestClassWithRange.create!(foo: 'abc', bar: 123)
701
-
702
- expect(TestClassWithRange.exists?('abc', 'nonexistent range key')).to eq(false)
703
- end
704
-
705
- end
706
- end
707
-
708
-
709
560
  describe '#new_record?' do
710
561
  it 'should return true for a new record' do
711
562
  expect(Dynamini::Base.new).to be_truthy
@@ -0,0 +1,178 @@
1
+ require 'spec_helper'
2
+
3
+ describe Dynamini::Querying 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
+ subject(:model) { Dynamini::Base.new(model_attributes) }
15
+
16
+ class TestClassWithRange < Dynamini::Base
17
+ set_hash_key :foo
18
+ set_range_key :bar
19
+ self.in_memory = true
20
+ handle :bar, :integer
21
+ end
22
+
23
+ describe '.find' do
24
+
25
+ before do
26
+ model.save
27
+ end
28
+
29
+ it 'should return a model with the retrieved attributes' do
30
+ found = Dynamini::Base.find('abcd1234')
31
+ expect(found.price).to eq(9.99)
32
+ expect(found.name).to eq('Widget')
33
+ expect(found.hash_key).to eq('009')
34
+ end
35
+
36
+ context 'when the object does not exist' do
37
+ it 'should raise an error' do
38
+ expect { Dynamini::Base.find('f') }.to raise_error 'Item not found.'
39
+ end
40
+
41
+ end
42
+
43
+ context 'when retrieving a subclass' do
44
+ class Foo < Dynamini::Base
45
+ self.in_memory = true
46
+ end
47
+
48
+ it 'should return the object as an instance of the subclass' do
49
+ Foo.create(id: '1')
50
+ expect(Foo.find('1')).to be_a Foo
51
+ end
52
+ end
53
+ end
54
+
55
+ describe '.query' do
56
+ before do
57
+ 4.times do |i|
58
+ TestClassWithRange.create(foo: 'foo', bar: i + 1)
59
+ end
60
+ end
61
+ context 'start value provided' do
62
+ it 'should return records with a range key greater than or equal to the start value' do
63
+ records = TestClassWithRange.query(hash_key: 'foo', start: 2)
64
+ expect(records.length).to eq 3
65
+ expect(records.first.bar).to eq 2
66
+ expect(records.last.bar).to eq 4
67
+ end
68
+ end
69
+ context 'end value provided' do
70
+ it 'should return records with a range key less than or equal to the start value' do
71
+ records = TestClassWithRange.query(hash_key: 'foo', end: 2)
72
+ expect(records.length).to eq 2
73
+ expect(records.first.bar).to eq 1
74
+ expect(records.last.bar).to eq 2
75
+ end
76
+ end
77
+ context 'start and end values provided' do
78
+ it 'should return records between the two values inclusive' do
79
+ records = TestClassWithRange.query(hash_key: 'foo', start: 1, end: 3)
80
+ expect(records.length).to eq 3
81
+ expect(records.first.bar).to eq 1
82
+ expect(records.last.bar).to eq 3
83
+ end
84
+ end
85
+ context 'neither value provided' do
86
+ it 'should return all records belonging to that hash key' do
87
+ records = TestClassWithRange.query(hash_key: 'foo')
88
+ expect(records.length).to eq 4
89
+ expect(records.first.bar).to eq 1
90
+ expect(records.last.bar).to eq 4
91
+ end
92
+ end
93
+
94
+ context 'a non-numeric range field' do
95
+ it 'should raise an error' do
96
+ class TestClassWithStringRange < Dynamini::Base
97
+ self.in_memory = true
98
+ set_hash_key :group
99
+ set_range_key :user_name
100
+ end
101
+ expect { TestClassWithStringRange.query(hash_key: 'registered', start: 'a') }.to raise_error TypeError
102
+ end
103
+ end
104
+
105
+ context 'hash key does not exist' do
106
+ it 'should return an empty array' do
107
+ expect(TestClassWithRange.query(hash_key: 'non-existent key')).to eq([])
108
+ end
109
+ end
110
+ end
111
+
112
+ describe '.exists?' do
113
+ context 'with hash key' do
114
+ context 'the item exists' do
115
+ before do
116
+ model.save
117
+ end
118
+ it 'should return true' do
119
+ expect(Dynamini::Base.exists?(model_attributes[:id])).to be_truthy
120
+ end
121
+ end
122
+
123
+ context 'the item does not exist' do
124
+ it 'should return false' do
125
+ expect(Dynamini::Base.exists?('nonexistent id')).to eq(false)
126
+ end
127
+ end
128
+ end
129
+
130
+ context 'with hash key and range key' do
131
+
132
+ it 'should return true if item exists' do
133
+ TestClassWithRange.create!(foo: 'abc', bar: 123)
134
+
135
+ expect(TestClassWithRange.exists?('abc', 123)).to eq(true)
136
+ end
137
+
138
+ it 'should return false if the item does not exist' do
139
+ TestClassWithRange.create!(foo: 'abc', bar: 123)
140
+
141
+ expect(TestClassWithRange.exists?('abc', 'nonexistent range key')).to eq(false)
142
+ end
143
+ end
144
+ end
145
+
146
+ describe '.find_or_new' do
147
+ context 'when a record with the given key exists' do
148
+ before do
149
+ model.save
150
+ end
151
+ it 'should return that record' do
152
+ existing_record = Dynamini::Base.find_or_new(model.id)
153
+ expect(existing_record.new_record?).to eq(false)
154
+ expect(existing_record.id).to eq(model.id)
155
+ end
156
+
157
+ it 'should return the record for table with range key' do
158
+ existing_record = TestClassWithRange.create!(foo: 1, bar: 123)
159
+ expect(TestClassWithRange.find_or_new(existing_record.foo, existing_record.bar).new_record?).to eq(false)
160
+ expect(existing_record.foo).to eq(1)
161
+ expect(existing_record.bar).to eq(123)
162
+ end
163
+
164
+ end
165
+ context 'when the key cannot be found' do
166
+ it 'should initialize a new object with that key' do
167
+ expect(Dynamini::Base.find_or_new('foo').new_record?).to be_truthy
168
+ end
169
+
170
+ it 'should initialize a new object with hash key and range key' do
171
+ new_record = TestClassWithRange.find_or_new(1, 6)
172
+ expect(new_record.new_record?).to be_truthy
173
+ expect(new_record.foo).to eq(1)
174
+ expect(new_record.bar).to eq(6)
175
+ end
176
+ end
177
+ end
178
+ 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.10.1
4
+ version: 1.10.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Greg Ward
@@ -21,104 +21,104 @@ dependencies:
21
21
  name: activemodel
22
22
  requirement: !ruby/object:Gem::Requirement
23
23
  requirements:
24
- - - ">="
24
+ - - '>='
25
25
  - !ruby/object:Gem::Version
26
26
  version: '3'
27
- - - "<"
27
+ - - <
28
28
  - !ruby/object:Gem::Version
29
29
  version: '5.0'
30
30
  type: :runtime
31
31
  prerelease: false
32
32
  version_requirements: !ruby/object:Gem::Requirement
33
33
  requirements:
34
- - - ">="
34
+ - - '>='
35
35
  - !ruby/object:Gem::Version
36
36
  version: '3'
37
- - - "<"
37
+ - - <
38
38
  - !ruby/object:Gem::Version
39
39
  version: '5.0'
40
40
  - !ruby/object:Gem::Dependency
41
41
  name: aws-sdk
42
42
  requirement: !ruby/object:Gem::Requirement
43
43
  requirements:
44
- - - "~>"
44
+ - - ~>
45
45
  - !ruby/object:Gem::Version
46
46
  version: '2'
47
47
  type: :runtime
48
48
  prerelease: false
49
49
  version_requirements: !ruby/object:Gem::Requirement
50
50
  requirements:
51
- - - "~>"
51
+ - - ~>
52
52
  - !ruby/object:Gem::Version
53
53
  version: '2'
54
54
  - !ruby/object:Gem::Dependency
55
55
  name: rspec
56
56
  requirement: !ruby/object:Gem::Requirement
57
57
  requirements:
58
- - - "~>"
58
+ - - ~>
59
59
  - !ruby/object:Gem::Version
60
60
  version: '3'
61
61
  type: :development
62
62
  prerelease: false
63
63
  version_requirements: !ruby/object:Gem::Requirement
64
64
  requirements:
65
- - - "~>"
65
+ - - ~>
66
66
  - !ruby/object:Gem::Version
67
67
  version: '3'
68
68
  - !ruby/object:Gem::Dependency
69
69
  name: pry
70
70
  requirement: !ruby/object:Gem::Requirement
71
71
  requirements:
72
- - - "~>"
72
+ - - ~>
73
73
  - !ruby/object:Gem::Version
74
74
  version: '0'
75
75
  type: :development
76
76
  prerelease: false
77
77
  version_requirements: !ruby/object:Gem::Requirement
78
78
  requirements:
79
- - - "~>"
79
+ - - ~>
80
80
  - !ruby/object:Gem::Version
81
81
  version: '0'
82
82
  - !ruby/object:Gem::Dependency
83
83
  name: fuubar
84
84
  requirement: !ruby/object:Gem::Requirement
85
85
  requirements:
86
- - - "~>"
86
+ - - ~>
87
87
  - !ruby/object:Gem::Version
88
88
  version: '2'
89
89
  type: :development
90
90
  prerelease: false
91
91
  version_requirements: !ruby/object:Gem::Requirement
92
92
  requirements:
93
- - - "~>"
93
+ - - ~>
94
94
  - !ruby/object:Gem::Version
95
95
  version: '2'
96
96
  - !ruby/object:Gem::Dependency
97
97
  name: guard-rspec
98
98
  requirement: !ruby/object:Gem::Requirement
99
99
  requirements:
100
- - - ">="
100
+ - - '>='
101
101
  - !ruby/object:Gem::Version
102
102
  version: '0'
103
103
  type: :development
104
104
  prerelease: false
105
105
  version_requirements: !ruby/object:Gem::Requirement
106
106
  requirements:
107
- - - ">="
107
+ - - '>='
108
108
  - !ruby/object:Gem::Version
109
109
  version: '0'
110
110
  - !ruby/object:Gem::Dependency
111
111
  name: guard-shell
112
112
  requirement: !ruby/object:Gem::Requirement
113
113
  requirements:
114
- - - ">="
114
+ - - '>='
115
115
  - !ruby/object:Gem::Version
116
116
  version: '0'
117
117
  type: :development
118
118
  prerelease: false
119
119
  version_requirements: !ruby/object:Gem::Requirement
120
120
  requirements:
121
- - - ">="
121
+ - - '>='
122
122
  - !ruby/object:Gem::Version
123
123
  version: '0'
124
124
  description: |-
@@ -130,9 +130,9 @@ executables: []
130
130
  extensions: []
131
131
  extra_rdoc_files: []
132
132
  files:
133
- - ".gitignore"
134
- - ".rspec"
135
- - ".travis.yml"
133
+ - .gitignore
134
+ - .rspec
135
+ - .travis.yml
136
136
  - Gemfile
137
137
  - Gemfile.lock
138
138
  - Guardfile
@@ -145,9 +145,11 @@ files:
145
145
  - lib/dynamini/base.rb
146
146
  - lib/dynamini/batch_operations.rb
147
147
  - lib/dynamini/configuration.rb
148
+ - lib/dynamini/querying.rb
148
149
  - lib/dynamini/test_client.rb
149
150
  - spec/dynamini/base_spec.rb
150
151
  - spec/dynamini/batch_operations_spec.rb
152
+ - spec/dynamini/querying_spec.rb
151
153
  - spec/dynamini/test_client_spec.rb
152
154
  - spec/spec_helper.rb
153
155
  homepage: https://github.com/47colborne/dynamini
@@ -160,22 +162,23 @@ require_paths:
160
162
  - lib
161
163
  required_ruby_version: !ruby/object:Gem::Requirement
162
164
  requirements:
163
- - - ">="
165
+ - - '>='
164
166
  - !ruby/object:Gem::Version
165
167
  version: '0'
166
168
  required_rubygems_version: !ruby/object:Gem::Requirement
167
169
  requirements:
168
- - - ">="
170
+ - - '>='
169
171
  - !ruby/object:Gem::Version
170
172
  version: '0'
171
173
  requirements: []
172
174
  rubyforge_project:
173
- rubygems_version: 2.4.6
175
+ rubygems_version: 2.2.2
174
176
  signing_key:
175
177
  specification_version: 4
176
178
  summary: DynamoDB interface
177
179
  test_files:
178
180
  - spec/dynamini/base_spec.rb
179
181
  - spec/dynamini/batch_operations_spec.rb
182
+ - spec/dynamini/querying_spec.rb
180
183
  - spec/dynamini/test_client_spec.rb
181
184
  - spec/spec_helper.rb