dynamini 2.5.0 → 2.6.0

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: af37a6a457e3643934e6d1f3900254c824069313
4
- data.tar.gz: a094c3596ee5b2614c4a30798739b1ee97353d32
3
+ metadata.gz: c71e8851f1dcde97317c1fd5034423cb4698a823
4
+ data.tar.gz: e62c81d4d011bc3bc99365dd577a6d11e054fdda
5
5
  SHA512:
6
- metadata.gz: 32cc0f359b3b9272059aeb92faed3ef27b54c7b7120d068517d1a63a420e37ff1fe83afcc9e023f12939421b1b4ada06e10f17e4182cff6c879ed8a9cf3386cd
7
- data.tar.gz: 2031fabc0a87a412a04cdb3d1b31fed1a0b68ef6183d74eabc3a1f97d16e2f7d53176e665eb3a4481f9bbb40dd2a294ae3eda263a8f84b4e501d00912016c9a8
6
+ metadata.gz: 65bb9e2e742706642974c9509100afc9c96fb1f71a1d06fb32413b342b7b61a613e4687c88ee4364ddd5b9663074794c028601eb4b5403720ce3395ca005ce7c
7
+ data.tar.gz: acd5c9f3c9b30a2c5e512493348f7acc6fde4ffaa25cdd667519999b8f58ee7ca80613b0507da5b2cc03b9de92c622bcac8bc06bb9f3ddf901d3acea3da8c44e
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- dynamini (2.4.0)
4
+ dynamini (2.6.0)
5
5
  activemodel (>= 3, < 5.0)
6
6
  aws-sdk (~> 2)
7
7
 
@@ -17,12 +17,12 @@ GEM
17
17
  minitest (~> 5.1)
18
18
  thread_safe (~> 0.3, >= 0.3.4)
19
19
  tzinfo (~> 1.1)
20
- aws-sdk (2.5.3)
21
- aws-sdk-resources (= 2.5.3)
22
- aws-sdk-core (2.5.3)
20
+ aws-sdk (2.6.1)
21
+ aws-sdk-resources (= 2.6.1)
22
+ aws-sdk-core (2.6.1)
23
23
  jmespath (~> 1.0)
24
- aws-sdk-resources (2.5.3)
25
- aws-sdk-core (= 2.5.3)
24
+ aws-sdk-resources (2.6.1)
25
+ aws-sdk-core (= 2.6.1)
26
26
  builder (3.2.2)
27
27
  coderay (1.1.0)
28
28
  diff-lcs (1.2.5)
@@ -99,3 +99,6 @@ DEPENDENCIES
99
99
  guard-shell
100
100
  pry (~> 0)
101
101
  rspec (~> 3)
102
+
103
+ BUNDLED WITH
104
+ 1.12.5
data/README.md CHANGED
@@ -98,10 +98,50 @@ The following datatypes are supported by handle:
98
98
  * :date
99
99
  * :time
100
100
  * :string
101
+ * :array
101
102
 
102
103
  Booleans and strings don't actually need to be translated, but you can set up defaults for those fields this way.
103
104
  The magic fields updated_at and created_at are handled as :time by default.
104
105
 
106
+ ## Array Support
107
+ You can save arrays to your Dynamini model. Optionally, you can have Dynamini perform type conversion on each element of your array. Here's how it works:
108
+
109
+ ```ruby
110
+ class Vehicle < Dynamini::Base
111
+ set_hash_key :vin
112
+ handle :parts, :array, of: :symbol # :of accepts the same types as :handle
113
+ handle :other_array, :array
114
+ end
115
+
116
+ car = Vehicle.new(vin: 'H3LL0')
117
+ car.parts
118
+ > []
119
+
120
+ car.parts = 'wheel'
121
+ car.parts
122
+ > :wheel
123
+
124
+ car.parts = ['wheel', 'brakes', 'seat']
125
+ car.parts
126
+ > [:wheel, :brakes, :seat]
127
+
128
+ # This line will raise an error since 5 cannot be converted to a symbol.
129
+ car.parts = ['wheel', 'brakes', 5]
130
+
131
+ # If you want a multitype array, invoke :handle without the :of option.
132
+ car.other_array = ['wheel', 'brakes', 5]
133
+ car.other_array
134
+ > ['wheel', 'brakes', 5]
135
+ # But then you won't have any type conversion.
136
+ car.save
137
+ Vehicle.find('H3LLO').other_array
138
+ > ['wheel', 'brakes', BigDecimal(5)]
139
+ ```
140
+
141
+ Please note that changing arrays in place using mutator methods like << or map! will not record a change to the object.
142
+
143
+ If you want to make changes like this, either clone it then use the assignment operator (e.g. model.array = model.array.dup << 'foo') or call model.mark(:attribute) after mutation and before saving to force Dynamini to write the change.
144
+
105
145
  ## Querying With Range Keys
106
146
 
107
147
  Dynamini includes a query function that's much more narrow than ActiveRecord's where function. It's designed to retrieve a selection of records that belong to a given hash key but have various range key values. To use .query, your table needs to be configured with a range key, and you need to :handle that range field as a fundamentally numeric type - integer, float, date, or time. If your range key field isn't numeric, you won't be able to .query, but you'll still be able to .find your records normally.
@@ -154,44 +194,6 @@ DailyWeather.query(hash_key: "Toronto", scan_index_forward: false)
154
194
  > [C, B, A]
155
195
  ```
156
196
 
157
- ## Array Support
158
- You can save arrays to your Dynamini model. If you've :handled that attribute, it will attempt to convert its contents to the correct datatype when setting and getting. Here's how it works:
159
-
160
- ```ruby
161
- class Vehicle < Dynamini::Base
162
- set_hash_key :vin
163
- handle :parts, :symbol, default: []
164
- end
165
-
166
- car = Vehicle.new(vin: 'H3LL0')
167
- car.parts
168
- > []
169
-
170
- car.parts = 'wheel'
171
- car.parts
172
- > :wheel
173
-
174
- car.parts = ['wheel', 'brakes', 'seat']
175
- car.parts
176
- > [:wheel, :brakes, :seat]
177
-
178
- # This line will raise an error since 5 cannot be converted to a symbol.
179
- car.parts = ['wheel', 'brakes', 5]
180
-
181
- # That multitype array can be saved to a non-:handled attribute.
182
- car.stuff = ['wheel', 'brakes', 5]
183
- car.stuff
184
- > ['wheel', 'brakes', 5]
185
- # But then you won't have any type conversion.
186
- car.save
187
- Vehicle.find('H3LLO').stuff
188
- > ['wheel', 'brakes', BigDecimal(5)]
189
- ```
190
-
191
- Please note that changing arrays in place using mutator methods like << or map! will not record a change to the object.
192
-
193
- If you want to make changes like this, either clone it then use the assignment operator (e.g. model.array = model.array.dup << 'foo') or call model.mark(:attribute) after mutation and before saving to force Dynamini to write the change.
194
-
195
197
  ## Testing
196
198
  We've included an optional in-memory test client, so you don't necessarily have to connect to a real Dynamo instance when running tests. You could also use this in your development environment if you don't have a real Dynamo instance yet, but the data saved to it won't persist through a server restart.
197
199
 
@@ -1,6 +1,6 @@
1
1
  Gem::Specification.new do |s|
2
2
  s.name = 'dynamini'
3
- s.version = '2.5.0'
3
+ s.version = '2.6.0'
4
4
  s.summary = 'DynamoDB interface'
5
5
  s.description = 'Lightweight DynamoDB interface gem designed as
6
6
  a drop-in replacement for ActiveRecord.
@@ -0,0 +1,25 @@
1
+ module Dynamini
2
+ module Adder
3
+ def add_to(attribute, value)
4
+ complain_about(attribute) unless handles[attribute]
5
+ old_value = read_attribute(attribute)
6
+ add_value = attribute_callback(Dynamini::TypeHandler::SETTER_PROCS, handles[attribute], value)
7
+ case handles[attribute][:format]
8
+ when :set, :array
9
+ @attributes[attribute] += add_value
10
+ when :integer, :float, :time, :date
11
+ @attributes[attribute] += add_value
12
+ else
13
+ complain_about(attribute)
14
+ end
15
+ record_change(attribute, old_value, add_value, 'ADD')
16
+ self
17
+ end
18
+
19
+ private
20
+
21
+ def complain_about(attribute)
22
+ raise ArgumentError, "#{attribute.capitalize} is not handled as an addable type. Addable types are set, array, integer, float, time, and date."
23
+ end
24
+ end
25
+ end
@@ -4,6 +4,7 @@ require_relative 'client_interface'
4
4
  require_relative 'dirty'
5
5
  require_relative 'increment'
6
6
  require_relative 'type_handler'
7
+ require_relative 'adder'
7
8
 
8
9
  module Dynamini
9
10
  # Core db interface class.
@@ -16,6 +17,8 @@ module Dynamini
16
17
  include Dynamini::Dirty
17
18
  include Dynamini::Increment
18
19
  include Dynamini::TypeHandler
20
+ include Dynamini::Adder
21
+
19
22
 
20
23
  attr_reader :attributes
21
24
  class_attribute :handles
@@ -74,7 +77,7 @@ module Dynamini
74
77
  @attributes = {}
75
78
  clear_changes
76
79
  attributes.each do |k, v|
77
- write_attribute(k, v, new_record)
80
+ write_attribute(k, v, change: new_record)
78
81
  end
79
82
  end
80
83
 
@@ -174,7 +177,7 @@ module Dynamini
174
177
  def attribute_updates
175
178
  changes.reduce({}) do |updates, (key, value)|
176
179
  current_value = value[1]
177
- updates[key] = { value: current_value, action: 'PUT' }
180
+ updates[key] = { value: current_value, action: value[2] || 'PUT' }
178
181
  updates
179
182
  end
180
183
  end
@@ -207,13 +210,13 @@ module Dynamini
207
210
  @attributes.keys.include?(name) || write_method?(name) || was_method?(name) || super
208
211
  end
209
212
 
210
- def write_attribute(attribute, new_value, change = true)
213
+ def write_attribute(attribute, new_value, change: true, **options)
211
214
  old_value = read_attribute(attribute)
212
215
  if (handle = handles[attribute.to_sym]) && !new_value.nil?
213
216
  new_value = attribute_callback(SETTER_PROCS, handle, new_value)
214
217
  end
215
218
  @attributes[attribute] = new_value
216
- record_change(attribute, new_value, old_value) if change && new_value != old_value
219
+ record_change(attribute, old_value, new_value, options[:action]) if change && new_value != old_value
217
220
  end
218
221
 
219
222
  def read_attribute(name)
@@ -15,16 +15,17 @@ module Dynamini
15
15
  end
16
16
 
17
17
  def mark(attr)
18
- if @changes[attr] == [nil, nil]
18
+ if @changes[attr][0..1] == [nil, nil]
19
19
  val = @attributes[attr]
20
- @changes[attr] = [val, val]
20
+ @changes[attr][0..1] = [val, val]
21
21
  end
22
22
  end
23
23
 
24
24
  private
25
25
 
26
- def record_change(attribute, new_value, old_value)
27
- @changes[attribute] = [old_value, new_value]
26
+ def record_change(attribute, old_value, new_value, action)
27
+ action ||= 'PUT'
28
+ @changes[attribute] = [old_value, new_value, action]
28
29
  end
29
30
 
30
31
  def clear_changes
@@ -9,7 +9,8 @@ module Dynamini
9
9
  symbol: proc { |v| v.to_sym },
10
10
  string: proc { |v| v },
11
11
  boolean: proc { |v| v },
12
- array: proc { |v| v }
12
+ array: proc { |v| v },
13
+ set: proc { |v| v }
13
14
  }
14
15
 
15
16
  SETTER_PROCS = {
@@ -20,12 +21,14 @@ module Dynamini
20
21
  string: proc { |v| v },
21
22
  boolean: proc { |v| v },
22
23
  date: proc { |v| v.to_time.to_f },
23
- array: proc { |v| v }
24
+ array: proc { |v| v },
25
+ set: proc { |v| v }
24
26
  }
25
27
 
26
28
  module ClassMethods
27
29
  def handle(column, format_class, options = {})
28
- options[:default] ||= [] if format_class == :array
30
+ options[:default] ||= format_default(format_class)
31
+ options[:default] ||= Set.new if format_class == :set
29
32
 
30
33
  self.handles = self.handles.merge(column => { format: format_class, options: options })
31
34
 
@@ -50,6 +53,15 @@ module Dynamini
50
53
  write_attribute(column, value)
51
54
  end
52
55
  end
56
+
57
+ def format_default(format_class)
58
+ case format_class
59
+ when :array
60
+ []
61
+ when :set
62
+ Set.new
63
+ end
64
+ end
53
65
  end
54
66
 
55
67
  private
@@ -61,20 +73,24 @@ module Dynamini
61
73
  def attribute_callback(procs, handle, value)
62
74
  type = handle[:options][:of] || handle[:format]
63
75
  callback = procs[type]
64
-
65
- if handle_as_array?(handle, value)
76
+ if value.is_a?(Array)
66
77
  value.map { |e| callback.call(e) }
78
+ elsif value.is_a?(Set)
79
+ Set.new(value.map { |e| callback.call(e) })
80
+ elsif handled_as?(handle, [:array, :set])
81
+ raise ArgumentError, "Can't write a non-enumerable value to field handled as #{handle[:format]}"
67
82
  else
68
83
  callback.call(value)
69
84
  end
70
85
  end
71
86
 
72
- def handle_as_array?(handle, value)
73
- handle[:format] == :array || value.is_a?(Array)
87
+ def handled_as?(handle, type)
88
+ type.include? handle[:format]
74
89
  end
75
90
 
76
91
  def self.included(base)
77
92
  base.extend ClassMethods
78
93
  end
94
+
79
95
  end
80
96
  end
@@ -0,0 +1,82 @@
1
+ require 'spec_helper'
2
+
3
+ describe Dynamini::Adder do
4
+
5
+ class AddHandledModel < Dynamini::Base
6
+ handle :price, :float
7
+ handle :things, :set
8
+ handle :stuff, :array
9
+ handle :when, :date
10
+ handle :what_time, :time
11
+ handle :widget_count, :integer
12
+ end
13
+
14
+ let(:model_attributes) {
15
+ {
16
+ name: 'Widget',
17
+ price: 9.99,
18
+ id: 'abcd1234',
19
+ hash_key: '009',
20
+ things: Set.new([1,2,3]),
21
+ stuff: [4,5,6]
22
+ }
23
+ }
24
+
25
+ let(:model) { AddHandledModel.new(model_attributes, false) }
26
+
27
+
28
+ describe '.add_to' do
29
+ context 'a change exists for the given attribute' do
30
+ it 'should overwrite the change with a change that adds to the previously set value' do
31
+ model.price = 2
32
+ model.add_to(:price, 3)
33
+ expect(model.price).to eq(5)
34
+ expect(model.changes['price']).to eq([2, 3, 'ADD'])
35
+ end
36
+ end
37
+
38
+ context 'no change exists for the given attribute' do
39
+ it 'should create an add change' do
40
+ model.add_to(:price, 2)
41
+ expect(model.price).to eq(11.99)
42
+ expect(model.changes['price']).to eq([9.99, 2, 'ADD'])
43
+ end
44
+ end
45
+
46
+ context 'a setter is called after adding' do
47
+ it 'should overwrite the ADD change with a PUT change' do
48
+ model.add_to(:price, 2)
49
+ model.price = 2
50
+ expect(model.changes['price']).to eq([11.99, 2, 'PUT'])
51
+ end
52
+ end
53
+
54
+ context 'adding to a set' do
55
+ context 'the provided value is enumerable' do
56
+ it 'merges the sets' do
57
+ model.add_to(:things, Set.new([4]))
58
+ expect(model.things).to eq(Set.new([1,2,3,4]))
59
+ end
60
+ end
61
+ context 'the provided value is not enumerable' do
62
+ it 'raises an error' do
63
+ expect{ model.add_to(:things, 4) }.to raise_error ArgumentError
64
+ end
65
+ end
66
+ end
67
+
68
+ context 'adding to an array' do
69
+ context 'the provided value is enumerable' do
70
+ it 'merges the arrays' do
71
+ model.add_to(:stuff, [7])
72
+ expect(model.stuff).to eq([4,5,6,7])
73
+ end
74
+ end
75
+ context 'the provided value is not enumerable' do
76
+ it 'raises an error' do
77
+ expect{ model.add_to(:stuff, 4) }.to raise_error ArgumentError
78
+ end
79
+ end
80
+ end
81
+ end
82
+ end
@@ -16,8 +16,6 @@ describe Dynamini::Dirty do
16
16
 
17
17
 
18
18
  describe '.new' do
19
-
20
-
21
19
  it 'should append all initial attrs to @changed, including hash_key' do
22
20
  expect(dirty_model.changed).to eq(model_attributes.keys.map(&:to_s).delete_if { |k, v| k == 'id' })
23
21
  end
@@ -37,7 +35,7 @@ describe Dynamini::Dirty do
37
35
  context 'when marking an already changed attribute' do
38
36
  it 'should do nothing' do
39
37
  dirty_model.mark(:price)
40
- expect(dirty_model.changes['price']).to eq([nil, model_attributes[:price]])
38
+ expect(dirty_model.changes['price']).to eq([nil, model_attributes[:price], 'PUT'])
41
39
  end
42
40
  end
43
41
  context 'when using it to mark a changed array' do
@@ -138,14 +136,26 @@ describe Dynamini::Dirty do
138
136
  context 'attribute changed' do
139
137
  before { model.price = 1 }
140
138
  it 'should include the changed attribute' do
141
- expect(model.changes['price']).to eq([9.99, 1])
139
+ expect(model.changes['price']).to eq([9.99, 1, 'PUT'])
140
+ end
141
+ end
142
+
143
+ context 'attribute changed with ADD action' do
144
+
145
+ class AddModel < Dynamini::Base
146
+ handle :price, :float
147
+ end
148
+ it 'should include a change with ADD action specified' do
149
+ model = AddModel.create!(model_attributes)
150
+ model.add_to(:price, 1)
151
+ expect(model.changes['price']).to eq([9.99, 1, 'ADD'])
142
152
  end
143
153
  end
144
154
 
145
155
  context 'attribute created' do
146
156
  before { model.foo = 'bar' }
147
157
  it 'should include the created attribute' do
148
- expect(model.changes['foo']).to eq([nil, 'bar'])
158
+ expect(model.changes['foo']).to eq([nil, 'bar', 'PUT'])
149
159
  end
150
160
  end
151
161
 
@@ -155,7 +165,7 @@ describe Dynamini::Dirty do
155
165
  model.foo = 'baz'
156
166
  end
157
167
  it 'should only include one copy of the changed attribute' do
158
- expect(model.changes['foo']).to eq(['bar', 'baz'])
168
+ expect(model.changes['foo']).to eq(['bar', 'baz', 'PUT'])
159
169
  end
160
170
  end
161
171
  end
@@ -32,6 +32,7 @@ describe Dynamini::Querying do
32
32
  expect(found.price).to eq(9.99)
33
33
  expect(found.name).to eq('Widget')
34
34
  expect(found.hash_key).to eq('009')
35
+ expect(found).to_not be_new_record
35
36
  end
36
37
 
37
38
  context 'when the object does not exist' do
@@ -254,4 +255,4 @@ describe Dynamini::Querying do
254
255
  end
255
256
  end
256
257
  end
257
- end
258
+ end
@@ -19,6 +19,13 @@ describe Dynamini::TestClient do
19
19
  test_client.update_item(table_name: table_name, key: {hash_key_name: 'hash_key_value'}, attribute_updates: {abc: {value: 'def', action: 'PUT'}})
20
20
  expect(test_client.data[table_name]['hash_key_value']).to eq(abc: 'def', :hash_key_name => "hash_key_value")
21
21
  end
22
+
23
+ it 'ADDs integers' do
24
+ test_client = Dynamini::TestClient.new(:hash_key_name)
25
+ test_client.update_item(table_name: table_name, key: {hash_key_name: 'hash_key_value'}, attribute_updates: {abc: {value: 1, action: 'PUT'}})
26
+ test_client.update_item(table_name: table_name, key: {hash_key_name: 'hash_key_value'}, attribute_updates: {abc: {value: 1, action: 'ADD'}})
27
+ expect(test_client.data[table_name]['hash_key_value']).to eq(abc: 2, hash_key_name: 'hash_key_value')
28
+ end
22
29
  end
23
30
 
24
31
  context 'with Hash key and range key' do
@@ -57,6 +64,7 @@ describe Dynamini::TestClient do
57
64
  end
58
65
 
59
66
  describe '#get_item' do
67
+
60
68
  context 'table with just a hash key' do
61
69
  let(:test_client) { Dynamini::TestClient.new(:hash_key_name) }
62
70
 
@@ -41,6 +41,10 @@ describe Dynamini::TypeHandler do
41
41
  handle :defaulted_ary, :array, default: [1,2,3]
42
42
  handle :float_array, :array, of: :float
43
43
  handle :sym_array, :array, of: :symbol
44
+ handle :my_set, :set
45
+ handle :defaulted_set, :set, default: Set.new([1,2,3])
46
+ handle :sym_set, :set, of: :symbol
47
+ handle :float_set, :set, of: :float
44
48
  end
45
49
 
46
50
  let(:handle_model) { HandleModel.new }
@@ -71,25 +75,52 @@ describe Dynamini::TypeHandler do
71
75
  expect { handle_model.int_list = {a: 1} }.to raise_error NoMethodError
72
76
  end
73
77
 
74
- it 'should retrieve casted float arrays' do
75
- handle_model.float_array = [12, 24, 48]
76
- expectations = [12.0, 24.0, 48.0]
77
- handle_model.float_array.each_with_index do |e, i|
78
- expect(e).to equal(expectations[i])
79
- end
78
+ it 'should reject non-enumerable data for enumerable handles' do
79
+ expect { handle_model.my_set = 2 }.to raise_error ArgumentError
80
+ expect { handle_model.ary = 2}.to raise_error ArgumentError
80
81
  end
81
82
 
82
- it 'should retrieve casted symbol arrays' do
83
- handle_model.sym_array = ['foo', 'bar', 'baz']
84
- expect(handle_model.sym_array).to eq([:foo, :bar, :baz])
85
- end
83
+ context 'when handling as array' do
84
+ it 'should retrieve casted float arrays' do
85
+ handle_model.float_array = [12, 24, 48]
86
+ expectations = [12.0, 24.0, 48.0]
87
+ handle_model.float_array.each_with_index do |e, i|
88
+ expect(e).to equal(expectations[i])
89
+ end
90
+ end
91
+
92
+ it 'should retrieve casted symbol arrays' do
93
+ handle_model.sym_array = ['foo', 'bar', 'baz']
94
+ expect(handle_model.sym_array).to eq([:foo, :bar, :baz])
95
+ end
96
+
97
+ it 'should default arrays to []' do
98
+ expect(handle_model.ary).to eq([])
99
+ end
86
100
 
87
- it 'should default arrays to []' do
88
- expect(handle_model.ary).to eq([])
101
+ it 'should allow default values for arrays' do
102
+ expect(handle_model.defaulted_ary).to eq([1, 2, 3])
103
+ end
89
104
  end
90
105
 
91
- it 'should allow default values for arrays' do
92
- expect(handle_model.defaulted_ary).to eq([1, 2, 3])
106
+ context 'when handling as set' do
107
+ it 'should retrieve casted float sets' do
108
+ handle_model.float_set = Set.new([12, 24, 48])
109
+ expect(handle_model.float_set).to eq(Set.new([12.0, 24.0, 48.0]))
110
+ end
111
+
112
+ it 'should retrieve casted symbol arrays' do
113
+ handle_model.sym_set = Set.new(['foo', 'bar', 'baz'])
114
+ expect(handle_model.sym_set).to eq(Set.new([:foo, :bar, :baz]))
115
+ end
116
+
117
+ it 'should default sets to empty sets' do
118
+ expect(handle_model.my_set).to eq(Set.new)
119
+ end
120
+
121
+ it 'should allow default values for arrays' do
122
+ expect(handle_model.defaulted_ary).to eq([1, 2, 3])
123
+ end
93
124
  end
94
125
 
95
126
  context 'legacy support' do
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: 2.5.0
4
+ version: 2.6.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Greg Ward
@@ -15,7 +15,7 @@ authors:
15
15
  autorequire:
16
16
  bindir: bin
17
17
  cert_chain: []
18
- date: 2016-09-15 00:00:00.000000000 Z
18
+ date: 2016-09-21 00:00:00.000000000 Z
19
19
  dependencies:
20
20
  - !ruby/object:Gem::Dependency
21
21
  name: activemodel
@@ -142,6 +142,7 @@ files:
142
142
  - dynamini.gemspec
143
143
  - lib/.DS_Store
144
144
  - lib/dynamini.rb
145
+ - lib/dynamini/adder.rb
145
146
  - lib/dynamini/base.rb
146
147
  - lib/dynamini/batch_operations.rb
147
148
  - lib/dynamini/client_interface.rb
@@ -153,6 +154,7 @@ files:
153
154
  - lib/dynamini/test_client.rb
154
155
  - lib/dynamini/testing.rb
155
156
  - lib/dynamini/type_handler.rb
157
+ - spec/dynamini/adder_spec.rb
156
158
  - spec/dynamini/base_spec.rb
157
159
  - spec/dynamini/batch_operations_spec.rb
158
160
  - spec/dynamini/dirty_spec.rb
@@ -187,6 +189,7 @@ signing_key:
187
189
  specification_version: 4
188
190
  summary: DynamoDB interface
189
191
  test_files:
192
+ - spec/dynamini/adder_spec.rb
190
193
  - spec/dynamini/base_spec.rb
191
194
  - spec/dynamini/batch_operations_spec.rb
192
195
  - spec/dynamini/dirty_spec.rb