dynamini 1.10.2 → 1.10.4

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,144 @@
1
+ require 'spec_helper'
2
+
3
+ describe Dynamini::Dirty do
4
+
5
+ let(:model_attributes) {
6
+ {
7
+ name: 'Widget',
8
+ price: 9.99,
9
+ id: 'abcd1234',
10
+ hash_key: '009'
11
+ }
12
+ }
13
+ let(:dirty_model) { Dynamini::Base.new(model_attributes) }
14
+ let(:model) { Dynamini::Base.new(model_attributes, false) }
15
+
16
+
17
+ describe '.new' do
18
+
19
+
20
+ it 'should append all initial attrs to @changed, including hash_key' do
21
+ expect(dirty_model.changed).to eq(model_attributes.keys.map(&:to_s).delete_if { |k, v| k == 'id' })
22
+ end
23
+
24
+ it 'should not include the primary key in the changes' do
25
+ expect(dirty_model.changes[:id]).to be_nil
26
+ end
27
+ end
28
+
29
+ describe '#__was' do
30
+
31
+ context 'nonexistent attribute' do
32
+ it 'should raise an error' do
33
+ expect { Dynamini::Base.new.thing_was }.to raise_error ArgumentError
34
+ end
35
+ end
36
+
37
+ context 'after saving' do
38
+ it 'should clear all _was values' do
39
+ model = Dynamini::Base.new
40
+ model.new_val = 'new'
41
+ model.save
42
+ expect(model.new_val_was).to eq('new')
43
+ end
44
+ end
45
+
46
+ context 'new record' do
47
+
48
+ subject(:model) { Dynamini::Base.new(baz: 'baz') }
49
+ it { is_expected.to respond_to(:baz_was) }
50
+
51
+ context 'handled attribute with default' do
52
+ it 'should return the default value' do
53
+ Dynamini::Base.handle(:num, :integer, default: 2)
54
+ expect(model.num_was).to eq(2)
55
+ end
56
+ end
57
+
58
+ context 'handled attribute with no default' do
59
+ it 'should return nil' do
60
+ Dynamini::Base.handle(:num, :integer)
61
+ expect(model.num_was).to be_nil
62
+ end
63
+ end
64
+
65
+ context 'newly assigned attribute' do
66
+ it 'should return nil' do
67
+ model.new_attribute = 'hello'
68
+ expect(model.new_attribute_was).to be_nil
69
+ end
70
+ end
71
+ end
72
+
73
+ context 'previously saved record' do
74
+ subject(:model) { Dynamini::Base.new({baz: 'baz', nil_val: nil}, false) }
75
+ context 'unchanged attribute' do
76
+ it 'should return the current value' do
77
+ expect(model.baz_was).to eq('baz')
78
+ end
79
+ end
80
+
81
+ context 'newly assigned attribute or attribute changed from explicit nil' do
82
+ it 'should return nil' do
83
+ model.nil_val = 'no longer nil'
84
+ model.new_val = 'new'
85
+ expect(model.nil_val_was).to be_nil
86
+ expect(model.new_val_was).to be_nil
87
+ end
88
+ end
89
+
90
+ context 'attribute changed from value to value' do
91
+ it 'should return the old value' do
92
+ model.baz = 'baz2'
93
+ expect(model.baz_was).to eq('baz')
94
+ end
95
+ end
96
+ end
97
+ end
98
+
99
+ describe '#changes' do
100
+ it 'should not return the hash key or range key' do
101
+ Dynamini::Base.set_range_key(:range_key)
102
+ model.instance_variable_set(:@changes, {id: 'test_hash_key', range_key: "test_range_key"})
103
+ expect(model.changes).to eq({})
104
+ Dynamini::Base.set_range_key(nil)
105
+ end
106
+
107
+ context 'no change detected' do
108
+ it 'should return an empty hash' do
109
+ expect(model.changes).to eq({})
110
+ end
111
+ end
112
+
113
+ context 'attribute changed' do
114
+ before { model.price = 1 }
115
+ it 'should include the changed attribute' do
116
+ expect(model.changes['price']).to eq([9.99, 1])
117
+ end
118
+ end
119
+
120
+ context 'attribute created' do
121
+ before { model.foo = 'bar' }
122
+ it 'should include the created attribute' do
123
+ expect(model.changes['foo']).to eq([nil, 'bar'])
124
+ end
125
+ end
126
+
127
+ context 'attribute changed twice' do
128
+ before do
129
+ model.foo = 'bar'
130
+ model.foo = 'baz'
131
+ end
132
+ it 'should only include one copy of the changed attribute' do
133
+ expect(model.changes['foo']).to eq(['bar', 'baz'])
134
+ end
135
+ end
136
+ end
137
+
138
+ describe '#changed' do
139
+ it 'should stringify the keys of changes' do
140
+ allow(model).to receive(:changes).and_return({'price' => [1, 2], 'name' => ['a', 'b']})
141
+ expect(model.changed).to eq(['price', 'name'])
142
+ end
143
+ end
144
+ end
@@ -0,0 +1,88 @@
1
+ require 'spec_helper'
2
+
3
+ describe Dynamini::Increment 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.create!(model_attributes) }
15
+
16
+ describe '.increment!' do
17
+ context 'when incrementing a nil value' do
18
+ it 'should save' do
19
+ expect(model.class.client).to receive(:update_item).with(
20
+ table_name: 'bases',
21
+ key: {id: model_attributes[:id]},
22
+ attribute_updates: hash_including(
23
+ "foo" => {
24
+ value: 5,
25
+ action: 'ADD'
26
+ }
27
+ )
28
+ )
29
+ model.increment!(foo: 5)
30
+ end
31
+ it 'should update the value' do
32
+ model.increment!(foo: 5)
33
+ expect(Dynamini::Base.find('abcd1234').foo.to_i).to eq 5
34
+ end
35
+ end
36
+ context 'when incrementing a numeric value' do
37
+ it 'should save' do
38
+ expect(model).to receive(:read_attribute).and_return(9.99)
39
+ expect(model.class.client).to receive(:update_item).with(
40
+ table_name: 'bases',
41
+ key: {id: model_attributes[:id]},
42
+ attribute_updates: hash_including(
43
+ "price" => {
44
+ value: 5,
45
+ action: 'ADD'
46
+ }
47
+ )
48
+ )
49
+ model.increment!(price: 5)
50
+
51
+ end
52
+ it 'should sum the values' do
53
+ expect(model).to receive(:read_attribute).and_return(9.99)
54
+ model.increment!(price: 5)
55
+ expect(Dynamini::Base.find('abcd1234').price).to eq 14.99
56
+ end
57
+ end
58
+ context 'when incrementing a non-numeric value' do
59
+ it 'should raise an error and not save' do
60
+ expect(model).to receive(:read_attribute).and_return('hello')
61
+ expect { model.increment!(price: 5) }.to raise_error(StandardError)
62
+ end
63
+ end
64
+ context 'when incrementing with a non-numeric value' do
65
+ it 'should raise an error and not save' do
66
+ expect { model.increment!(foo: 'bar') }.to raise_error(StandardError)
67
+ end
68
+ end
69
+ context 'when incrementing multiple values' do
70
+ it 'should create/sum both values' do
71
+ allow(model).to receive(:read_attribute).and_return(9.99)
72
+ model.increment!(price: 5, baz: 6)
73
+ found_model = Dynamini::Base.find('abcd1234')
74
+ expect(found_model.price).to eq 14.99
75
+ expect(found_model.baz).to eq 6
76
+ end
77
+ end
78
+ context 'when incrementing a new record' do
79
+ it 'should save the record and init the values and timestamps' do
80
+ Dynamini::Base.new(id: 1, foo: 'bar').increment!(baz: 1)
81
+ found_model = Dynamini::Base.find(1)
82
+ expect(found_model.baz).to eq 1
83
+ expect(found_model.created_at).to_not be_nil
84
+ expect(found_model.updated_at).to_not be_nil
85
+ end
86
+ end
87
+ end
88
+ end
@@ -0,0 +1,79 @@
1
+ require 'spec_helper'
2
+
3
+ describe Dynamini::TypeHandler do
4
+ describe '.handle' do
5
+
6
+ class HandledClass < Dynamini::Base;
7
+ end
8
+
9
+ context 'when reading the handled attirubte' do
10
+ before { HandledClass.handle :price, :integer, default: 9 }
11
+ it 'should return the proper format' do
12
+ object = HandledClass.new(price: "1")
13
+ expect(object.price).to eq(1)
14
+ end
15
+ it 'should return the default value if not assigned' do
16
+ object = HandledClass.new
17
+ expect(object.price).to eq(9)
18
+ end
19
+ it 'should return an array with formated item if handled' do
20
+ object = HandledClass.new(price: ["1", "2"])
21
+ expect(object.price).to eq([1, 2])
22
+ end
23
+ end
24
+
25
+ context 'when writing the handled attribute' do
26
+ before { HandledClass.handle :price, :float, default: 9 }
27
+ it 'should convert the value to handled format' do
28
+ object = HandledClass.new(price: "1")
29
+ expect(object.attributes[:price]).to eq(1.0)
30
+ end
31
+ end
32
+
33
+ end
34
+
35
+ class HandleModel < Dynamini::Base
36
+ handle :price, :float, default: 10
37
+ handle :start_date, :time
38
+ handle :int_list, :integer
39
+ handle :sym_list, :symbol
40
+ end
41
+
42
+ let(:handle_model) { HandleModel.new }
43
+
44
+ it 'should create getters and setters' do
45
+ expect(handle_model).to_not receive(:method_missing)
46
+ handle_model.price = 1
47
+ handle_model.price
48
+ end
49
+
50
+ it 'should retrieve price as a float' do
51
+ handle_model.price = '5.2'
52
+ expect(handle_model.price).to be_a(Float)
53
+ end
54
+
55
+ it 'should default price to 0 if not set' do
56
+ expect(handle_model.price).to eq 10
57
+ end
58
+
59
+ it 'should store times as floats' do
60
+ handle_model.start_date = Time.now
61
+ expect(handle_model.attributes[:start_date]).to be_a(Float)
62
+ expect(handle_model.attributes[:start_date] > 1_000_000_000).to be_truthy
63
+ expect(handle_model.start_date).to be_a(Time)
64
+ end
65
+
66
+ it 'should reject bad data' do
67
+ expect { handle_model.int_list = {a: 1} }.to raise_error NoMethodError
68
+ end
69
+
70
+ it 'should save casted arrays' do
71
+ handle_model.int_list = [12, 24, 48]
72
+ expect(handle_model.int_list).to eq([12, 24, 48])
73
+ end
74
+
75
+ it 'should retrieve casted arrays' do
76
+ handle_model.sym_list = ['foo', 'bar', 'baz']
77
+ expect(handle_model.sym_list).to eq([:foo, :bar, :baz])
78
+ end
79
+ 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.2
4
+ version: 1.10.4
5
5
  platform: ruby
6
6
  authors:
7
7
  - Greg Ward
@@ -15,110 +15,110 @@ authors:
15
15
  autorequire:
16
16
  bindir: bin
17
17
  cert_chain: []
18
- date: 2015-01-07 00:00:00.000000000 Z
18
+ date: 2015-01-11 00:00:00.000000000 Z
19
19
  dependencies:
20
20
  - !ruby/object:Gem::Dependency
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
@@ -144,13 +144,21 @@ files:
144
144
  - lib/dynamini.rb
145
145
  - lib/dynamini/base.rb
146
146
  - lib/dynamini/batch_operations.rb
147
+ - lib/dynamini/client_interface.rb
147
148
  - lib/dynamini/configuration.rb
149
+ - lib/dynamini/dirty.rb
150
+ - lib/dynamini/increment.rb
148
151
  - lib/dynamini/querying.rb
149
152
  - lib/dynamini/test_client.rb
153
+ - lib/dynamini/type_handler.rb
150
154
  - spec/dynamini/base_spec.rb
151
155
  - spec/dynamini/batch_operations_spec.rb
156
+ - spec/dynamini/client_interface_spec.rb
157
+ - spec/dynamini/dirty_spec.rb
158
+ - spec/dynamini/increment_spec.rb
152
159
  - spec/dynamini/querying_spec.rb
153
160
  - spec/dynamini/test_client_spec.rb
161
+ - spec/dynamini/type_handler_spec.rb
154
162
  - spec/spec_helper.rb
155
163
  homepage: https://github.com/47colborne/dynamini
156
164
  licenses:
@@ -162,23 +170,27 @@ require_paths:
162
170
  - lib
163
171
  required_ruby_version: !ruby/object:Gem::Requirement
164
172
  requirements:
165
- - - '>='
173
+ - - ">="
166
174
  - !ruby/object:Gem::Version
167
175
  version: '0'
168
176
  required_rubygems_version: !ruby/object:Gem::Requirement
169
177
  requirements:
170
- - - '>='
178
+ - - ">="
171
179
  - !ruby/object:Gem::Version
172
180
  version: '0'
173
181
  requirements: []
174
182
  rubyforge_project:
175
- rubygems_version: 2.2.2
183
+ rubygems_version: 2.4.6
176
184
  signing_key:
177
185
  specification_version: 4
178
186
  summary: DynamoDB interface
179
187
  test_files:
180
188
  - spec/dynamini/base_spec.rb
181
189
  - spec/dynamini/batch_operations_spec.rb
190
+ - spec/dynamini/client_interface_spec.rb
191
+ - spec/dynamini/dirty_spec.rb
192
+ - spec/dynamini/increment_spec.rb
182
193
  - spec/dynamini/querying_spec.rb
183
194
  - spec/dynamini/test_client_spec.rb
195
+ - spec/dynamini/type_handler_spec.rb
184
196
  - spec/spec_helper.rb