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 +4 -4
- data/Gemfile.lock +9 -6
- data/README.md +40 -38
- data/dynamini.gemspec +1 -1
- data/lib/dynamini/adder.rb +25 -0
- data/lib/dynamini/base.rb +7 -4
- data/lib/dynamini/dirty.rb +5 -4
- data/lib/dynamini/type_handler.rb +23 -7
- data/spec/dynamini/adder_spec.rb +82 -0
- data/spec/dynamini/dirty_spec.rb +16 -6
- data/spec/dynamini/querying_spec.rb +2 -1
- data/spec/dynamini/test_client_spec.rb +8 -0
- data/spec/dynamini/type_handler_spec.rb +45 -14
- metadata +5 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: c71e8851f1dcde97317c1fd5034423cb4698a823
|
4
|
+
data.tar.gz: e62c81d4d011bc3bc99365dd577a6d11e054fdda
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 65bb9e2e742706642974c9509100afc9c96fb1f71a1d06fb32413b342b7b61a613e4687c88ee4364ddd5b9663074794c028601eb4b5403720ce3395ca005ce7c
|
7
|
+
data.tar.gz: acd5c9f3c9b30a2c5e512493348f7acc6fde4ffaa25cdd667519999b8f58ee7ca80613b0507da5b2cc03b9de92c622bcac8bc06bb9f3ddf901d3acea3da8c44e
|
data/Gemfile.lock
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
dynamini (2.
|
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.
|
21
|
-
aws-sdk-resources (= 2.
|
22
|
-
aws-sdk-core (2.
|
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.
|
25
|
-
aws-sdk-core (= 2.
|
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
|
|
data/dynamini.gemspec
CHANGED
@@ -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
|
data/lib/dynamini/base.rb
CHANGED
@@ -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
|
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,
|
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)
|
data/lib/dynamini/dirty.rb
CHANGED
@@ -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,
|
27
|
-
|
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] ||=
|
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
|
73
|
-
handle[:format]
|
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
|
data/spec/dynamini/dirty_spec.rb
CHANGED
@@ -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
|
75
|
-
handle_model.
|
76
|
-
|
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
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
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
|
-
|
88
|
-
|
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
|
-
|
92
|
-
|
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.
|
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-
|
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
|