dynamini 2.6.4 → 2.6.5
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.
- checksums.yaml +4 -4
- data/Gemfile.lock +2 -2
- data/dynamini.gemspec +1 -1
- data/lib/dynamini/adder.rb +1 -1
- data/lib/dynamini/base.rb +14 -9
- data/lib/dynamini/querying.rb +1 -0
- data/lib/dynamini/test_client.rb +0 -2
- data/lib/dynamini/type_handler.rb +44 -48
- data/spec/dynamini/querying_spec.rb +63 -0
- data/spec/dynamini/test_client_spec.rb +18 -1
- metadata +3 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: a58fb603731e3efd1d91be0295a9f9c6bb9ab563
|
4
|
+
data.tar.gz: 914d82aa5c7e4c923e1f5d14552043bfab6f966b
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 35cef4e720792c20f78a3e9db934fc7fc020de29d06c377641fc4a4484b0874822394c391f0bc1dfb7a39a2310054efe68d665171c7900d523bd21fe92276cf1
|
7
|
+
data.tar.gz: c39c01e1d41bbceade9bf3eac3561766389e0763b308dd841e750e7e0440802809d1bcee273abc6d6b618e854aa8aa7f5377aab69b943ac4c6377d0783575591
|
data/Gemfile.lock
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
dynamini (2.6.
|
4
|
+
dynamini (2.6.5)
|
5
5
|
activemodel (>= 3, < 5.0)
|
6
6
|
aws-sdk (~> 2)
|
7
7
|
|
@@ -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.9.
|
59
|
+
minitest (5.9.1)
|
60
60
|
nenv (0.2.0)
|
61
61
|
notiffany (0.0.8)
|
62
62
|
nenv (~> 0.1)
|
data/dynamini.gemspec
CHANGED
data/lib/dynamini/adder.rb
CHANGED
@@ -6,7 +6,7 @@ module Dynamini
|
|
6
6
|
def add_to(attribute, value)
|
7
7
|
complain_about(attribute) unless handles[attribute]
|
8
8
|
old_value = read_attribute(attribute)
|
9
|
-
add_value = attribute_callback(
|
9
|
+
add_value = self.class.attribute_callback(TypeHandler::SETTER_PROCS, handles[attribute], value)
|
10
10
|
if ADDABLE_TYPES.include? handles[attribute][:format]
|
11
11
|
@attributes[attribute] ? @attributes[attribute] += add_value : @attributes[attribute] = add_value
|
12
12
|
else
|
data/lib/dynamini/base.rb
CHANGED
@@ -14,10 +14,10 @@ module Dynamini
|
|
14
14
|
extend ActiveModel::Callbacks
|
15
15
|
extend Dynamini::BatchOperations
|
16
16
|
extend Dynamini::Querying
|
17
|
+
extend Dynamini::TypeHandler
|
17
18
|
include Dynamini::ClientInterface
|
18
19
|
include Dynamini::Dirty
|
19
20
|
include Dynamini::Increment
|
20
|
-
include Dynamini::TypeHandler
|
21
21
|
include Dynamini::Adder
|
22
22
|
|
23
23
|
attr_reader :attributes
|
@@ -30,6 +30,8 @@ module Dynamini
|
|
30
30
|
|
31
31
|
define_model_callbacks :save
|
32
32
|
|
33
|
+
alias :read_attribute_for_serialization :send
|
34
|
+
|
33
35
|
class << self
|
34
36
|
|
35
37
|
attr_reader :range_key, :secondary_index
|
@@ -42,12 +44,14 @@ module Dynamini
|
|
42
44
|
@table_name = name
|
43
45
|
end
|
44
46
|
|
45
|
-
def set_hash_key(key)
|
47
|
+
def set_hash_key(key, format = nil)
|
46
48
|
@hash_key = key
|
49
|
+
handle(key, format) if format
|
47
50
|
end
|
48
51
|
|
49
|
-
def set_range_key(key)
|
52
|
+
def set_range_key(key, format = nil)
|
50
53
|
@range_key = key
|
54
|
+
handle(key, format) if format
|
51
55
|
end
|
52
56
|
|
53
57
|
def set_secondary_index(index_name, args)
|
@@ -168,8 +172,9 @@ module Dynamini
|
|
168
172
|
end
|
169
173
|
|
170
174
|
def self.create_key_hash(hash_value, range_value = nil)
|
171
|
-
|
172
|
-
key_hash
|
175
|
+
|
176
|
+
key_hash = {self.hash_key => handled_key(self.hash_key, hash_value)}
|
177
|
+
key_hash[self.range_key] = handled_key(self.range_key, range_value) if self.range_key
|
173
178
|
key_hash
|
174
179
|
end
|
175
180
|
|
@@ -211,8 +216,8 @@ module Dynamini
|
|
211
216
|
|
212
217
|
def write_attribute(attribute, new_value, change: true, **options)
|
213
218
|
old_value = read_attribute(attribute)
|
214
|
-
if (handle = handles[attribute.to_sym]) && !new_value.nil?
|
215
|
-
new_value = attribute_callback(SETTER_PROCS, handle, new_value)
|
219
|
+
if (handle = self.class.handles[attribute.to_sym]) && !new_value.nil?
|
220
|
+
new_value = self.class.attribute_callback(TypeHandler::SETTER_PROCS, handle, new_value)
|
216
221
|
end
|
217
222
|
@attributes[attribute] = new_value
|
218
223
|
record_change(attribute, old_value, new_value, options[:action]) if change && new_value != old_value
|
@@ -220,9 +225,9 @@ module Dynamini
|
|
220
225
|
|
221
226
|
def read_attribute(name)
|
222
227
|
value = @attributes[name]
|
223
|
-
if (handle = handles[name.to_sym])
|
228
|
+
if (handle = self.class.handles[name.to_sym])
|
224
229
|
value = handle[:options][:default] if value.nil?
|
225
|
-
value = attribute_callback(GETTER_PROCS, handle, value) unless value.nil?
|
230
|
+
value = self.class.attribute_callback(TypeHandler::GETTER_PROCS, handle, value) unless value.nil?
|
226
231
|
end
|
227
232
|
value
|
228
233
|
end
|
data/lib/dynamini/querying.rb
CHANGED
@@ -3,6 +3,7 @@ module Dynamini
|
|
3
3
|
OPTIONAL_QUERY_PARAMS = [:limit, :scan_index_forward]
|
4
4
|
|
5
5
|
def find(hash_value, range_value = nil)
|
6
|
+
fail ArgumentError, 'Hash key cannot be nil or empty.' if (hash_value.nil? || hash_value.blank?)
|
6
7
|
fail 'Range key cannot be blank.' if range_key && range_value.nil?
|
7
8
|
response = client.get_item(table_name: table_name, key: create_key_hash(hash_value, range_value))
|
8
9
|
|
data/lib/dynamini/test_client.rb
CHANGED
@@ -7,7 +7,7 @@ module Dynamini
|
|
7
7
|
time: proc { |v| Time.at(v.to_f) },
|
8
8
|
float: proc { |v| v.to_f },
|
9
9
|
symbol: proc { |v| v.to_sym },
|
10
|
-
string: proc { |v| v },
|
10
|
+
string: proc { |v| v.to_s },
|
11
11
|
boolean: proc { |v| v },
|
12
12
|
array: proc { |v| v.to_a },
|
13
13
|
set: proc { |v| Set.new(v) }
|
@@ -18,66 +18,66 @@ module Dynamini
|
|
18
18
|
time: proc { |v| (v.is_a?(Date) ? v.to_time : v).to_f },
|
19
19
|
float: proc { |v| v.to_f },
|
20
20
|
symbol: proc { |v| v.to_s },
|
21
|
-
string: proc { |v| v },
|
21
|
+
string: proc { |v| v.to_s },
|
22
22
|
boolean: proc { |v| v },
|
23
23
|
date: proc { |v| v.to_time.to_f },
|
24
24
|
array: proc { |v| v.to_a },
|
25
25
|
set: proc { |v| Set.new(v) }
|
26
26
|
}
|
27
27
|
|
28
|
-
|
29
|
-
|
30
|
-
validate_handle(format_class, options)
|
28
|
+
def handle(column, format_class, options = {})
|
29
|
+
validate_handle(format_class, options)
|
31
30
|
|
32
|
-
|
33
|
-
|
31
|
+
options[:default] ||= format_default(format_class)
|
32
|
+
options[:default] ||= Set.new if format_class == :set
|
34
33
|
|
35
|
-
|
34
|
+
self.handles = self.handles.merge(column => { format: format_class, options: options })
|
36
35
|
|
37
|
-
|
38
|
-
|
39
|
-
|
36
|
+
define_handled_getter(column, format_class, options)
|
37
|
+
define_handled_setter(column, format_class)
|
38
|
+
end
|
40
39
|
|
41
|
-
|
42
|
-
|
43
|
-
|
40
|
+
def define_handled_getter(column, format_class, _options = {})
|
41
|
+
proc = GETTER_PROCS[format_class]
|
42
|
+
fail 'Unsupported data type: ' + format_class.to_s if proc.nil?
|
44
43
|
|
45
|
-
|
46
|
-
|
47
|
-
end
|
44
|
+
define_method(column) do
|
45
|
+
read_attribute(column)
|
48
46
|
end
|
47
|
+
end
|
49
48
|
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
end
|
49
|
+
def define_handled_setter(column, format_class)
|
50
|
+
method_name = (column.to_s + '=')
|
51
|
+
proc = SETTER_PROCS[format_class]
|
52
|
+
fail 'Unsupported data type: ' + format_class.to_s if proc.nil?
|
53
|
+
define_method(method_name) do |value|
|
54
|
+
write_attribute(column, value)
|
57
55
|
end
|
56
|
+
end
|
58
57
|
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
end
|
58
|
+
def format_default(format_class)
|
59
|
+
case format_class
|
60
|
+
when :array
|
61
|
+
[]
|
62
|
+
when :set
|
63
|
+
Set.new
|
66
64
|
end
|
65
|
+
end
|
67
66
|
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
end
|
67
|
+
def validate_handle(format, options)
|
68
|
+
if format == :set
|
69
|
+
if options[:of] && [:set, :array].include?(options[:of])
|
70
|
+
raise ArgumentError, 'Invalid handle: cannot store non-primitive datatypes within a set.'
|
73
71
|
end
|
74
72
|
end
|
75
73
|
end
|
76
74
|
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
75
|
+
def handled_key(column, value)
|
76
|
+
if handle = handles[column]
|
77
|
+
attribute_callback(GETTER_PROCS, handle, value)
|
78
|
+
else
|
79
|
+
value
|
80
|
+
end
|
81
81
|
end
|
82
82
|
|
83
83
|
def attribute_callback(procs, handle, value)
|
@@ -92,14 +92,6 @@ module Dynamini
|
|
92
92
|
end
|
93
93
|
end
|
94
94
|
|
95
|
-
def handled_as?(handle, type)
|
96
|
-
type.include? handle[:format]
|
97
|
-
end
|
98
|
-
|
99
|
-
def self.included(base)
|
100
|
-
base.extend ClassMethods
|
101
|
-
end
|
102
|
-
|
103
95
|
def should_convert_elements?(handle, value)
|
104
96
|
handle[:options][:of] && (value.is_a?(Array) || value.is_a?(Set))
|
105
97
|
end
|
@@ -111,5 +103,9 @@ module Dynamini
|
|
111
103
|
def convert_elements(enumerable, callback)
|
112
104
|
enumerable.map { |e| callback.call(e) }
|
113
105
|
end
|
106
|
+
|
107
|
+
def handled_as?(handle, type)
|
108
|
+
type.include? handle[:format]
|
109
|
+
end
|
114
110
|
end
|
115
111
|
end
|
@@ -45,7 +45,14 @@ describe Dynamini::Querying do
|
|
45
45
|
TestClassWithRange.find('1', '2')
|
46
46
|
end.to raise_error Dynamini::RecordNotFound, "Couldn't find TestClassWithRange with 'foo'=1 and 'bar'=2"
|
47
47
|
end
|
48
|
+
end
|
48
49
|
|
50
|
+
context 'when finding a nil or empty id' do
|
51
|
+
it 'raises an error' do
|
52
|
+
expect{ Dynamini::Base.find('') }.to raise_error ArgumentError
|
53
|
+
expect{ Dynamini::Base.find([]) }.to raise_error ArgumentError
|
54
|
+
expect{ Dynamini::Base.find() }.to raise_error ArgumentError
|
55
|
+
end
|
49
56
|
end
|
50
57
|
|
51
58
|
context 'when retrieving a subclass' do
|
@@ -57,6 +64,62 @@ describe Dynamini::Querying do
|
|
57
64
|
expect(Foo.find('1')).to be_a Foo
|
58
65
|
end
|
59
66
|
end
|
67
|
+
|
68
|
+
context 'when hash key is not handled' do
|
69
|
+
context 'when finding a record by integer when hash key was string' do
|
70
|
+
it 'should raise an error' do
|
71
|
+
Dynamini::Base.create!(id: '123', foo: 'bar')
|
72
|
+
expect{ Dynamini::Base.find(123) }.to raise_error(Dynamini::RecordNotFound)
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
context 'when finding a record by string when hash key was integer' do
|
77
|
+
it 'should not find the item' do
|
78
|
+
Dynamini::Base.create!(id: 123, foo: 'bar')
|
79
|
+
expect{ Dynamini::Base.find('123') }.to raise_error(Dynamini::RecordNotFound)
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
context 'when hash key is handled as string' do
|
85
|
+
class StringHandledHash < Dynamini::Base
|
86
|
+
set_hash_key :id, :string
|
87
|
+
end
|
88
|
+
|
89
|
+
context 'when finding a record by integer when hash key was string' do
|
90
|
+
it 'should find the item' do
|
91
|
+
StringHandledHash.create!(id: '123', foo: 'bar')
|
92
|
+
expect(StringHandledHash.find(123).foo).to eq('bar')
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
context 'when finding a record by string when hash key was integer' do
|
97
|
+
it 'should find the item' do
|
98
|
+
StringHandledHash.create!(id: 123, foo: 'bar')
|
99
|
+
expect(StringHandledHash.find('123').foo).to eq('bar')
|
100
|
+
end
|
101
|
+
end
|
102
|
+
end
|
103
|
+
|
104
|
+
context 'when hash key is handled as integer' do
|
105
|
+
class IntegerHandledHash < Dynamini::Base
|
106
|
+
set_hash_key :id, :integer
|
107
|
+
end
|
108
|
+
|
109
|
+
context 'when finding a record by integer when hash key was string' do
|
110
|
+
it 'should the item' do
|
111
|
+
IntegerHandledHash.create!(id: '123', foo: 'bar')
|
112
|
+
expect(IntegerHandledHash.find(123).foo).to eq('bar')
|
113
|
+
end
|
114
|
+
end
|
115
|
+
|
116
|
+
context 'when finding a record by string when hash key was integer' do
|
117
|
+
it 'should find the item' do
|
118
|
+
IntegerHandledHash.create!(id: 123, foo: 'bar')
|
119
|
+
expect(IntegerHandledHash.find('123').foo).to eq('bar')
|
120
|
+
end
|
121
|
+
end
|
122
|
+
end
|
60
123
|
end
|
61
124
|
|
62
125
|
describe '.find_or_nil' do
|
@@ -81,7 +81,7 @@ describe Dynamini::TestClient do
|
|
81
81
|
expect(test_client.get_item(table_name: table_name, key: {test_client.hash_key_attr => "abc"}).item[:test_attr]).to eq('test')
|
82
82
|
end
|
83
83
|
|
84
|
-
it 'should
|
84
|
+
it 'should return nil if the item does not exist' do
|
85
85
|
expect(test_client.get_item(table_name: table_name, key: {test_client.hash_key_attr => "abc"}).item).to eq(nil)
|
86
86
|
end
|
87
87
|
|
@@ -116,6 +116,23 @@ describe Dynamini::TestClient do
|
|
116
116
|
expect(test_client.get_item(table_name: table_name, key: {test_client.range_key_attr => 'def'}).item).to eq(nil)
|
117
117
|
end
|
118
118
|
end
|
119
|
+
|
120
|
+
context 'hash key is not handled' do
|
121
|
+
let(:test_client) { Dynamini::TestClient.new(:hash_key_name) }
|
122
|
+
context 'getting a record by integer when hash key is string' do
|
123
|
+
it 'should not find the item' do
|
124
|
+
test_client.update_item(table_name: table_name, key: {test_client.hash_key_attr => '123'}, attribute_updates: {test_attr: {value: 'test', action: 'PUT'}})
|
125
|
+
expect(test_client.get_item(table_name: table_name, key: {test_client.range_key_attr => 123}).item).to eq(nil)
|
126
|
+
end
|
127
|
+
end
|
128
|
+
|
129
|
+
context 'getting a record by string when hash key is integer' do
|
130
|
+
it 'should not find the item' do
|
131
|
+
test_client.update_item(table_name: table_name, key: {test_client.hash_key_attr => 123}, attribute_updates: {test_attr: {value: 'test', action: 'PUT'}})
|
132
|
+
expect(test_client.get_item(table_name: table_name, key: {test_client.range_key_attr => '123'}).item).to eq(nil)
|
133
|
+
end
|
134
|
+
end
|
135
|
+
end
|
119
136
|
end
|
120
137
|
|
121
138
|
describe '#query' 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.6.
|
4
|
+
version: 2.6.5
|
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-
|
18
|
+
date: 2016-10-04 00:00:00.000000000 Z
|
19
19
|
dependencies:
|
20
20
|
- !ruby/object:Gem::Dependency
|
21
21
|
name: activemodel
|
@@ -185,7 +185,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
185
185
|
version: '0'
|
186
186
|
requirements: []
|
187
187
|
rubyforge_project:
|
188
|
-
rubygems_version: 2.
|
188
|
+
rubygems_version: 2.5.1
|
189
189
|
signing_key:
|
190
190
|
specification_version: 4
|
191
191
|
summary: DynamoDB interface
|