disposable 0.2.6 → 0.3.0
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/.travis.yml +4 -4
- data/CHANGES.md +5 -0
- data/README.md +4 -3
- data/disposable.gemspec +1 -1
- data/lib/disposable/twin/coercion.rb +12 -5
- data/lib/disposable/version.rb +1 -1
- data/test/twin/changed_test.rb +4 -5
- data/test/twin/coercion_test.rb +86 -54
- metadata +7 -7
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: ac8377b25f70507f4f8864eeb8305ece5340f560
|
4
|
+
data.tar.gz: 14c1b2c3dfd514fb4d0fdd26e827dfea2cecfb83
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 5102f0279af1bed8b3a614833dc066b2e29e1ddff062896dfa2519bf31c67709119461399b8a6d03bf27b277428e503290e5e7f58d70d645e3c2ea14803a3af7
|
7
|
+
data.tar.gz: 3a752d1130a9f3b391534d968bdffe5661d362ca40db1e1b3adf018948003c805b56b6b5ef34efb29c874ee9b559ba5af501f446f3eb74e43126ac60ef7a8a6e
|
data/.travis.yml
CHANGED
data/CHANGES.md
CHANGED
@@ -1,3 +1,8 @@
|
|
1
|
+
# 0.3.0
|
2
|
+
|
3
|
+
* Use [dry-types](https://github.com/dry-rb/dry-types) as a replacement for the deprecated virtus. You have to change to dry-types' constants.
|
4
|
+
* Add `:nilify` option to avoid processing blank strings.
|
5
|
+
|
1
6
|
# 0.2.6
|
2
7
|
|
3
8
|
* Manual accessors are no longer overridden when inheriting twin classes.
|
data/README.md
CHANGED
@@ -193,14 +193,16 @@ class AlbumTwin < Disposable::Twin
|
|
193
193
|
|
194
194
|
## Coercion
|
195
195
|
|
196
|
-
Twins can use [
|
196
|
+
Twins can use [dry-types](https://github.com/dry-rb/dry-types) coercion. This will override the setter in your twin, coerce the incoming value, and call the original setter. _Nothing more_ will happen.
|
197
|
+
|
198
|
+
Disposable already defines a module `Disposable::Twin::Coercion::Types` with all the Dry::Types built-in types. So you can use any of the types documented in http://dry-rb.org/gems/dry-types/built-in-types/.
|
197
199
|
|
198
200
|
```ruby
|
199
201
|
class AlbumTwin < Disposable::Twin
|
200
202
|
feature Coercion
|
201
203
|
feature Setup::SkipSetter
|
202
204
|
|
203
|
-
property :id, type:
|
205
|
+
property :id, type: Types::Form::Int
|
204
206
|
```
|
205
207
|
|
206
208
|
The `:type` option defines the coercion type. You may incluce `Setup::SkipSetter`, too, as otherwise the coercion will happen at initialization time and in the setter.
|
@@ -212,7 +214,6 @@ twin.id #=> 1
|
|
212
214
|
|
213
215
|
Again, coercion only happens in the setter.
|
214
216
|
|
215
|
-
|
216
217
|
## Defaults
|
217
218
|
|
218
219
|
Default values can be set via `:default`.
|
data/disposable.gemspec
CHANGED
@@ -26,6 +26,6 @@ Gem::Specification.new do |spec|
|
|
26
26
|
spec.add_development_dependency "minitest"
|
27
27
|
spec.add_development_dependency "activerecord"
|
28
28
|
spec.add_development_dependency "sqlite3"
|
29
|
-
spec.add_development_dependency "
|
29
|
+
spec.add_development_dependency "dry-types", "~> 0.6"
|
30
30
|
# spec.add_development_dependency "database_cleaner"
|
31
31
|
end
|
@@ -1,17 +1,24 @@
|
|
1
|
-
require "
|
1
|
+
require "dry-types"
|
2
2
|
|
3
|
-
# confession: i love virtus' coercion.
|
4
3
|
module Disposable::Twin::Coercion
|
4
|
+
module Types
|
5
|
+
include Dry::Types.module
|
6
|
+
end
|
7
|
+
|
5
8
|
module ClassMethods
|
6
9
|
def property(name, options={}, &block)
|
7
10
|
super(name, options, &block).tap do
|
8
|
-
coercing_setter!(name, options[:type])
|
11
|
+
coercing_setter!(name, options[:type], options[:nilify]) if options[:type] || options[:nilify]
|
9
12
|
end
|
10
13
|
end
|
11
14
|
|
12
|
-
def coercing_setter!(name, type)
|
15
|
+
def coercing_setter!(name, type, nilify=false)
|
16
|
+
type = type ? (Types::Form::Nil | type) : Types::Form::Nil if nilify
|
17
|
+
|
13
18
|
mod = Module.new do
|
14
|
-
define_method("#{name}=")
|
19
|
+
define_method("#{name}=") do |value|
|
20
|
+
super type.call(value)
|
21
|
+
end
|
15
22
|
end
|
16
23
|
include mod
|
17
24
|
end
|
data/lib/disposable/version.rb
CHANGED
data/test/twin/changed_test.rb
CHANGED
@@ -114,24 +114,23 @@ class ChangedWithCoercionTest < MiniTest::Spec
|
|
114
114
|
include Changed
|
115
115
|
include Coercion
|
116
116
|
|
117
|
-
property :released, type:
|
117
|
+
property :released, type: Types::Form::Bool
|
118
118
|
end
|
119
119
|
|
120
120
|
it do
|
121
121
|
twin = SongTwin.new(Song.new)
|
122
122
|
twin.changed?(:released).must_equal false
|
123
|
-
twin.released =
|
123
|
+
twin.released = 'true'
|
124
124
|
twin.released.must_equal true
|
125
125
|
twin.changed?(:released).must_equal true
|
126
126
|
end
|
127
127
|
|
128
128
|
it do
|
129
129
|
twin = SongTwin.new(Song.new(true))
|
130
|
-
twin.released = true
|
131
130
|
twin.changed?(:released).must_equal false
|
132
|
-
twin.released =
|
131
|
+
twin.released = 'true' # it coerces, then assigns, then compares, which makes this NOT changed.
|
133
132
|
twin.changed?(:released).must_equal false
|
134
|
-
twin.released = false
|
133
|
+
twin.released = 'false'
|
135
134
|
twin.changed?(:released).must_equal true
|
136
135
|
end
|
137
136
|
end
|
data/test/twin/coercion_test.rb
CHANGED
@@ -3,84 +3,116 @@ require "test_helper"
|
|
3
3
|
require "disposable/twin/coercion"
|
4
4
|
|
5
5
|
class CoercionTest < MiniTest::Spec
|
6
|
-
Band = Struct.new(:label)
|
7
6
|
|
8
|
-
class
|
9
|
-
def coerce(value)
|
10
|
-
value*2
|
11
|
-
end
|
12
|
-
end
|
13
|
-
|
14
|
-
class Twin < Disposable::Twin
|
7
|
+
class TwinWithSkipSetter < Disposable::Twin
|
15
8
|
feature Coercion
|
16
9
|
feature Setup::SkipSetter
|
17
10
|
|
18
11
|
property :id
|
19
|
-
property :released_at, :
|
12
|
+
property :released_at, type: Types::Form::DateTime
|
20
13
|
|
21
14
|
property :hit do
|
22
|
-
property :length, :
|
23
|
-
property :good, :
|
15
|
+
property :length, type: Types::Coercible::Int
|
16
|
+
property :good, type: Types::Bool
|
24
17
|
end
|
25
18
|
|
26
19
|
property :band do
|
27
20
|
property :label do
|
28
|
-
property :value, :
|
21
|
+
property :value, type: Types::Coercible::Float
|
29
22
|
end
|
30
23
|
end
|
31
24
|
end
|
32
25
|
|
33
|
-
|
34
|
-
|
26
|
+
describe "with Setup::SkipSetter" do
|
27
|
+
|
28
|
+
subject do
|
29
|
+
TwinWithSkipSetter.new(album)
|
30
|
+
end
|
31
|
+
|
32
|
+
let (:album) {
|
33
|
+
OpenStruct.new(
|
34
|
+
id: 1,
|
35
|
+
:released_at => "31/03/1981",
|
36
|
+
:hit => OpenStruct.new(:length => "312"),
|
37
|
+
:band => OpenStruct.new(:label => OpenStruct.new(:value => "9999.99"))
|
38
|
+
)
|
39
|
+
}
|
40
|
+
|
41
|
+
it "NOT coerce values in setup" do
|
42
|
+
subject.released_at.must_equal "31/03/1981"
|
43
|
+
subject.hit.length.must_equal "312"
|
44
|
+
subject.band.label.value.must_equal "9999.99"
|
45
|
+
end
|
46
|
+
|
47
|
+
|
48
|
+
it "coerce values when using a setter" do
|
49
|
+
subject.id = Object
|
50
|
+
subject.released_at = "30/03/1981"
|
51
|
+
subject.hit.length = "312"
|
52
|
+
subject.band.label.value = "9999.99"
|
53
|
+
|
54
|
+
subject.released_at.must_be_kind_of DateTime
|
55
|
+
subject.released_at.must_equal DateTime.parse("30/03/1981")
|
56
|
+
subject.hit.length.must_equal 312
|
57
|
+
subject.hit.good.must_equal nil
|
58
|
+
subject.band.label.value.must_equal 9999.99
|
59
|
+
end
|
35
60
|
end
|
36
61
|
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
:released_at => "31/03/1981",
|
41
|
-
:hit => OpenStruct.new(:length => "312"),
|
42
|
-
:band => Band.new(OpenStruct.new(:value => "9999.99"))
|
43
|
-
)
|
44
|
-
}
|
45
|
-
|
46
|
-
# it { subject.released_at.must_be_kind_of DateTime }
|
47
|
-
it { subject.released_at.must_equal "31/03/1981" } # NO coercion in setup.
|
48
|
-
it { subject.hit.length.must_equal "312" }
|
49
|
-
it { subject.band.label.value.must_equal "9999.99" }
|
50
|
-
|
51
|
-
|
52
|
-
it do
|
53
|
-
subject.id = Object
|
54
|
-
subject.released_at = "30/03/1981"
|
55
|
-
subject.hit.length = "312"
|
56
|
-
subject.band.label.value = "9999.99"
|
57
|
-
|
58
|
-
subject.id = Object
|
59
|
-
subject.released_at.must_be_kind_of DateTime
|
60
|
-
subject.released_at.must_equal DateTime.parse("30/03/1981")
|
61
|
-
subject.hit.length.must_equal 312
|
62
|
-
subject.hit.good.must_equal nil
|
63
|
-
subject.band.label.value.must_equal "9999.999999.99" # coercion happened once.
|
62
|
+
class TwinWithoutSkipSetter < Disposable::Twin
|
63
|
+
feature Coercion
|
64
|
+
property :id, type: Types::Coercible::Int
|
64
65
|
end
|
65
|
-
end
|
66
66
|
|
67
|
+
describe "without Setup::SkipSetter" do
|
67
68
|
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
69
|
+
subject do
|
70
|
+
TwinWithoutSkipSetter.new(OpenStruct.new(id: "1"))
|
71
|
+
end
|
72
|
+
|
73
|
+
it "coerce values in setup and when using a setter" do
|
74
|
+
subject.id.must_equal 1
|
75
|
+
subject.id = "2"
|
76
|
+
subject.id.must_equal 2
|
72
77
|
end
|
73
78
|
end
|
74
79
|
|
75
|
-
class
|
80
|
+
class TwinWithNilify < Disposable::Twin
|
76
81
|
feature Coercion
|
77
|
-
|
82
|
+
|
83
|
+
property :date_of_birth,
|
84
|
+
type: Types::Form::Date, nilify: true
|
85
|
+
property :date_of_death_by_unicorns,
|
86
|
+
type: Types::Form::Nil | Types::Form::Date
|
87
|
+
property :id, nilify: true
|
78
88
|
end
|
79
89
|
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
90
|
+
describe "with Nilify" do
|
91
|
+
|
92
|
+
subject do
|
93
|
+
TwinWithNilify.new(OpenStruct.new(date_of_birth: '1990-01-12',
|
94
|
+
date_of_death_by_unicorns: '2037-02-18',
|
95
|
+
id: 1))
|
96
|
+
end
|
97
|
+
|
98
|
+
it "coerce values correctly" do
|
99
|
+
subject.date_of_birth.must_equal Date.parse('1990-01-12')
|
100
|
+
subject.date_of_death_by_unicorns.must_equal Date.parse('2037-02-18')
|
101
|
+
end
|
102
|
+
|
103
|
+
it "coerce empty values to nil when using option nilify: true" do
|
104
|
+
subject.date_of_birth = ""
|
105
|
+
subject.date_of_birth.must_equal nil
|
106
|
+
end
|
107
|
+
|
108
|
+
it "coerce empty values to nil when using dry-types | operator" do
|
109
|
+
subject.date_of_death_by_unicorns = ""
|
110
|
+
subject.date_of_death_by_unicorns.must_equal nil
|
111
|
+
end
|
112
|
+
|
113
|
+
it "converts blank string to nil, without :type option" do
|
114
|
+
subject.id = ""
|
115
|
+
subject.id.must_equal nil
|
116
|
+
end
|
85
117
|
end
|
86
|
-
end
|
118
|
+
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: disposable
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.3.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Nick Sutterer
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2016-
|
11
|
+
date: 2016-04-02 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: uber
|
@@ -129,19 +129,19 @@ dependencies:
|
|
129
129
|
- !ruby/object:Gem::Version
|
130
130
|
version: '0'
|
131
131
|
- !ruby/object:Gem::Dependency
|
132
|
-
name:
|
132
|
+
name: dry-types
|
133
133
|
requirement: !ruby/object:Gem::Requirement
|
134
134
|
requirements:
|
135
|
-
- - "
|
135
|
+
- - "~>"
|
136
136
|
- !ruby/object:Gem::Version
|
137
|
-
version: '0'
|
137
|
+
version: '0.6'
|
138
138
|
type: :development
|
139
139
|
prerelease: false
|
140
140
|
version_requirements: !ruby/object:Gem::Requirement
|
141
141
|
requirements:
|
142
|
-
- - "
|
142
|
+
- - "~>"
|
143
143
|
- !ruby/object:Gem::Version
|
144
|
-
version: '0'
|
144
|
+
version: '0.6'
|
145
145
|
description: Decorators on top of your ORM layer.
|
146
146
|
email:
|
147
147
|
- apotonick@gmail.com
|