dry-types 0.8.1 → 0.9.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 +5 -10
- data/CHANGELOG.md +25 -1
- data/Gemfile +1 -3
- data/README.md +1 -1
- data/Rakefile +11 -2
- data/benchmarks/hash_schemas.rb +51 -0
- data/dry-types.gemspec +4 -3
- data/lib/dry/types.rb +10 -5
- data/lib/dry/types/array/member.rb +4 -0
- data/lib/dry/types/builder.rb +6 -7
- data/lib/dry/types/coercions.rb +6 -1
- data/lib/dry/types/coercions/form.rb +4 -4
- data/lib/dry/types/constrained.rb +10 -5
- data/lib/dry/types/constraints.rb +2 -1
- data/lib/dry/types/core.rb +3 -13
- data/lib/dry/types/decorator.rb +2 -2
- data/lib/dry/types/definition.rb +1 -1
- data/lib/dry/types/errors.rb +15 -22
- data/lib/dry/types/extensions.rb +3 -0
- data/lib/dry/types/extensions/maybe.rb +64 -0
- data/lib/dry/types/hash.rb +14 -0
- data/lib/dry/types/hash/schema.rb +95 -40
- data/lib/dry/types/options.rb +0 -2
- data/lib/dry/types/result.rb +26 -3
- data/lib/dry/types/safe.rb +7 -1
- data/lib/dry/types/sum.rb +9 -1
- data/lib/dry/types/version.rb +1 -1
- data/lib/spec/dry/types.rb +56 -0
- metadata +38 -42
- data/benchmarks/basic.rb +0 -57
- data/benchmarks/constrained.rb +0 -37
- data/lib/dry/types/hashify.rb +0 -12
- data/lib/dry/types/maybe.rb +0 -34
- data/lib/dry/types/struct.rb +0 -25
- data/lib/dry/types/struct/class_interface.rb +0 -107
- data/lib/dry/types/value.rb +0 -13
data/lib/dry/types/version.rb
CHANGED
@@ -0,0 +1,56 @@
|
|
1
|
+
RSpec.shared_examples_for 'Dry::Types::Definition without primitive' do
|
2
|
+
def be_boolean
|
3
|
+
satisfy { |x| x == true || x == false }
|
4
|
+
end
|
5
|
+
|
6
|
+
describe '#constrained?' do
|
7
|
+
it 'returns a boolean value' do
|
8
|
+
expect(type.constrained?).to be_boolean
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
describe '#default?' do
|
13
|
+
it 'returns a boolean value' do
|
14
|
+
expect(type.default?).to be_boolean
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
describe '#valid?' do
|
19
|
+
it 'returns a boolean value' do
|
20
|
+
expect(type.valid?(1)).to be_boolean
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
describe '#eql?' do
|
25
|
+
it 'has #eql? defined' do
|
26
|
+
expect(type).to eql(type)
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
describe '#==' do
|
31
|
+
it 'has #== defined' do
|
32
|
+
expect(type).to eq(type)
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
RSpec.shared_examples_for 'Dry::Types::Definition#meta' do
|
38
|
+
describe '#meta' do
|
39
|
+
it 'allows setting meta information' do
|
40
|
+
with_meta = type.meta(foo: :bar).meta(baz: '1')
|
41
|
+
|
42
|
+
expect(with_meta).to be_instance_of(type.class)
|
43
|
+
expect(with_meta.meta).to eql(foo: :bar, baz: '1')
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
RSpec.shared_examples_for Dry::Types::Definition do
|
49
|
+
it_behaves_like 'Dry::Types::Definition without primitive'
|
50
|
+
|
51
|
+
describe '#primitive' do
|
52
|
+
it 'returns a class' do
|
53
|
+
expect(type.primitive).to be_instance_of(Class)
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: dry-types
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.9.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Piotr Solnica
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2016-
|
11
|
+
date: 2016-09-21 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: concurrent-ruby
|
@@ -24,6 +24,20 @@ dependencies:
|
|
24
24
|
- - "~>"
|
25
25
|
- !ruby/object:Gem::Version
|
26
26
|
version: '1.0'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: dry-core
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '0.1'
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '0.1'
|
27
41
|
- !ruby/object:Gem::Dependency
|
28
42
|
name: dry-container
|
29
43
|
requirement: !ruby/object:Gem::Requirement
|
@@ -72,20 +86,20 @@ dependencies:
|
|
72
86
|
requirements:
|
73
87
|
- - "~>"
|
74
88
|
- !ruby/object:Gem::Version
|
75
|
-
version: '0.
|
89
|
+
version: '0.4'
|
76
90
|
- - ">="
|
77
91
|
- !ruby/object:Gem::Version
|
78
|
-
version: 0.
|
92
|
+
version: 0.4.0
|
79
93
|
type: :runtime
|
80
94
|
prerelease: false
|
81
95
|
version_requirements: !ruby/object:Gem::Requirement
|
82
96
|
requirements:
|
83
97
|
- - "~>"
|
84
98
|
- !ruby/object:Gem::Version
|
85
|
-
version: '0.
|
99
|
+
version: '0.4'
|
86
100
|
- - ">="
|
87
101
|
- !ruby/object:Gem::Version
|
88
|
-
version: 0.
|
102
|
+
version: 0.4.0
|
89
103
|
- !ruby/object:Gem::Dependency
|
90
104
|
name: inflecto
|
91
105
|
requirement: !ruby/object:Gem::Requirement
|
@@ -107,75 +121,61 @@ dependencies:
|
|
107
121
|
- !ruby/object:Gem::Version
|
108
122
|
version: 0.0.2
|
109
123
|
- !ruby/object:Gem::Dependency
|
110
|
-
name:
|
111
|
-
requirement: !ruby/object:Gem::Requirement
|
112
|
-
requirements:
|
113
|
-
- - ">="
|
114
|
-
- !ruby/object:Gem::Version
|
115
|
-
version: 0.0.1
|
116
|
-
type: :runtime
|
117
|
-
prerelease: false
|
118
|
-
version_requirements: !ruby/object:Gem::Requirement
|
119
|
-
requirements:
|
120
|
-
- - ">="
|
121
|
-
- !ruby/object:Gem::Version
|
122
|
-
version: 0.0.1
|
123
|
-
- !ruby/object:Gem::Dependency
|
124
|
-
name: ice_nine
|
124
|
+
name: bundler
|
125
125
|
requirement: !ruby/object:Gem::Requirement
|
126
126
|
requirements:
|
127
127
|
- - "~>"
|
128
128
|
- !ruby/object:Gem::Version
|
129
|
-
version: '
|
130
|
-
type: :
|
129
|
+
version: '1.6'
|
130
|
+
type: :development
|
131
131
|
prerelease: false
|
132
132
|
version_requirements: !ruby/object:Gem::Requirement
|
133
133
|
requirements:
|
134
134
|
- - "~>"
|
135
135
|
- !ruby/object:Gem::Version
|
136
|
-
version: '
|
136
|
+
version: '1.6'
|
137
137
|
- !ruby/object:Gem::Dependency
|
138
|
-
name:
|
138
|
+
name: rake
|
139
139
|
requirement: !ruby/object:Gem::Requirement
|
140
140
|
requirements:
|
141
141
|
- - "~>"
|
142
142
|
- !ruby/object:Gem::Version
|
143
|
-
version: '
|
143
|
+
version: '11.0'
|
144
144
|
type: :development
|
145
145
|
prerelease: false
|
146
146
|
version_requirements: !ruby/object:Gem::Requirement
|
147
147
|
requirements:
|
148
148
|
- - "~>"
|
149
149
|
- !ruby/object:Gem::Version
|
150
|
-
version: '
|
150
|
+
version: '11.0'
|
151
151
|
- !ruby/object:Gem::Dependency
|
152
|
-
name:
|
152
|
+
name: rspec
|
153
153
|
requirement: !ruby/object:Gem::Requirement
|
154
154
|
requirements:
|
155
155
|
- - "~>"
|
156
156
|
- !ruby/object:Gem::Version
|
157
|
-
version: '
|
157
|
+
version: '3.3'
|
158
158
|
type: :development
|
159
159
|
prerelease: false
|
160
160
|
version_requirements: !ruby/object:Gem::Requirement
|
161
161
|
requirements:
|
162
162
|
- - "~>"
|
163
163
|
- !ruby/object:Gem::Version
|
164
|
-
version: '
|
164
|
+
version: '3.3'
|
165
165
|
- !ruby/object:Gem::Dependency
|
166
|
-
name:
|
166
|
+
name: dry-monads
|
167
167
|
requirement: !ruby/object:Gem::Requirement
|
168
168
|
requirements:
|
169
169
|
- - "~>"
|
170
170
|
- !ruby/object:Gem::Version
|
171
|
-
version: '
|
171
|
+
version: '0.2'
|
172
172
|
type: :development
|
173
173
|
prerelease: false
|
174
174
|
version_requirements: !ruby/object:Gem::Requirement
|
175
175
|
requirements:
|
176
176
|
- - "~>"
|
177
177
|
- !ruby/object:Gem::Version
|
178
|
-
version: '
|
178
|
+
version: '0.2'
|
179
179
|
description: Type system for Ruby supporting coercions, constraints and complex types
|
180
180
|
like structs, value objects, enums etc.
|
181
181
|
email:
|
@@ -192,8 +192,7 @@ files:
|
|
192
192
|
- LICENSE
|
193
193
|
- README.md
|
194
194
|
- Rakefile
|
195
|
-
- benchmarks/
|
196
|
-
- benchmarks/constrained.rb
|
195
|
+
- benchmarks/hash_schemas.rb
|
197
196
|
- dry-types.gemspec
|
198
197
|
- lib/dry-types.rb
|
199
198
|
- lib/dry/types.rb
|
@@ -215,20 +214,18 @@ files:
|
|
215
214
|
- lib/dry/types/definition.rb
|
216
215
|
- lib/dry/types/enum.rb
|
217
216
|
- lib/dry/types/errors.rb
|
217
|
+
- lib/dry/types/extensions.rb
|
218
|
+
- lib/dry/types/extensions/maybe.rb
|
218
219
|
- lib/dry/types/form.rb
|
219
220
|
- lib/dry/types/hash.rb
|
220
221
|
- lib/dry/types/hash/schema.rb
|
221
|
-
- lib/dry/types/hashify.rb
|
222
222
|
- lib/dry/types/json.rb
|
223
|
-
- lib/dry/types/maybe.rb
|
224
223
|
- lib/dry/types/options.rb
|
225
224
|
- lib/dry/types/result.rb
|
226
225
|
- lib/dry/types/safe.rb
|
227
|
-
- lib/dry/types/struct.rb
|
228
|
-
- lib/dry/types/struct/class_interface.rb
|
229
226
|
- lib/dry/types/sum.rb
|
230
|
-
- lib/dry/types/value.rb
|
231
227
|
- lib/dry/types/version.rb
|
228
|
+
- lib/spec/dry/types.rb
|
232
229
|
homepage: https://github.com/dryrb/dry-types
|
233
230
|
licenses:
|
234
231
|
- MIT
|
@@ -242,7 +239,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
242
239
|
requirements:
|
243
240
|
- - ">="
|
244
241
|
- !ruby/object:Gem::Version
|
245
|
-
version:
|
242
|
+
version: 2.1.0
|
246
243
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
247
244
|
requirements:
|
248
245
|
- - ">="
|
@@ -256,4 +253,3 @@ specification_version: 4
|
|
256
253
|
summary: Type system for Ruby supporting coercions, constraints and complex types
|
257
254
|
like structs, value objects, enums etc.
|
258
255
|
test_files: []
|
259
|
-
has_rdoc:
|
data/benchmarks/basic.rb
DELETED
@@ -1,57 +0,0 @@
|
|
1
|
-
require 'dry/types'
|
2
|
-
require 'virtus'
|
3
|
-
require 'fast_attributes'
|
4
|
-
require 'attrio'
|
5
|
-
require 'ostruct'
|
6
|
-
|
7
|
-
require 'benchmark/ips'
|
8
|
-
|
9
|
-
class VirtusUser
|
10
|
-
include Virtus.model
|
11
|
-
|
12
|
-
attribute :name, String
|
13
|
-
attribute :age, Integer
|
14
|
-
end
|
15
|
-
|
16
|
-
class FastUser
|
17
|
-
extend FastAttributes
|
18
|
-
|
19
|
-
define_attributes initialize: true, attributes: true do
|
20
|
-
attribute :name, String
|
21
|
-
attribute :age, Integer
|
22
|
-
end
|
23
|
-
end
|
24
|
-
|
25
|
-
class AttrioUser
|
26
|
-
include Attrio
|
27
|
-
|
28
|
-
define_attributes do
|
29
|
-
attr :name, String
|
30
|
-
attr :age, Integer
|
31
|
-
end
|
32
|
-
|
33
|
-
def initialize(attributes = {})
|
34
|
-
self.attributes = attributes
|
35
|
-
end
|
36
|
-
|
37
|
-
def attributes=(attributes = {})
|
38
|
-
attributes.each do |attr,value|
|
39
|
-
self.send("#{attr}=", value) if self.respond_to?("#{attr}=")
|
40
|
-
end
|
41
|
-
end
|
42
|
-
end
|
43
|
-
|
44
|
-
class DryTypesUser < Dry::Types::Struct
|
45
|
-
attributes(name: 'string', age: 'form.int')
|
46
|
-
end
|
47
|
-
|
48
|
-
puts DryTypesUser.new(name: 'Jane', age: '21').inspect
|
49
|
-
|
50
|
-
Benchmark.ips do |x|
|
51
|
-
x.report('virtus') { VirtusUser.new(name: 'Jane', age: '21') }
|
52
|
-
x.report('fast_attributes') { FastUser.new(name: 'Jane', age: '21') }
|
53
|
-
x.report('attrio') { AttrioUser.new(name: 'Jane', age: '21') }
|
54
|
-
x.report('dry-types') { DryTypesUser.new(name: 'Jane', age: '21') }
|
55
|
-
|
56
|
-
x.compare!
|
57
|
-
end
|
data/benchmarks/constrained.rb
DELETED
@@ -1,37 +0,0 @@
|
|
1
|
-
require 'dry/types'
|
2
|
-
|
3
|
-
require 'active_record'
|
4
|
-
require 'benchmark/ips'
|
5
|
-
|
6
|
-
ActiveRecord::Base.establish_connection(adapter: "sqlite3", database: ":memory:")
|
7
|
-
|
8
|
-
ActiveRecord::Schema.define do
|
9
|
-
create_table :users do |table|
|
10
|
-
table.column :name, :string
|
11
|
-
table.column :age, :integer
|
12
|
-
end
|
13
|
-
end
|
14
|
-
|
15
|
-
class ARUser < ActiveRecord::Base
|
16
|
-
self.table_name = :users
|
17
|
-
end
|
18
|
-
|
19
|
-
module Types
|
20
|
-
include Dry::Types.module
|
21
|
-
end
|
22
|
-
|
23
|
-
class DryTypesUser < Dry::Types::Struct
|
24
|
-
attribute :id, Types::Form::Int
|
25
|
-
attribute :name, Types::Strict::String.constrained(size: 3..64)
|
26
|
-
attribute :age, Types::Form::Int.constrained(gt: 18)
|
27
|
-
end
|
28
|
-
|
29
|
-
puts ARUser.new(id: 1, name: 'Jane', age: '21').inspect
|
30
|
-
puts DryTypesUser.new(id: 1, name: 'Jane', age: '21').inspect
|
31
|
-
|
32
|
-
Benchmark.ips do |x|
|
33
|
-
x.report('active record') { ARUser.new(id: 1, name: 'Jane', age: '21') }
|
34
|
-
x.report('dry-types') { DryTypesUser.new(id: 1, name: 'Jane', age: '21') }
|
35
|
-
|
36
|
-
x.compare!
|
37
|
-
end
|
data/lib/dry/types/hashify.rb
DELETED
data/lib/dry/types/maybe.rb
DELETED
@@ -1,34 +0,0 @@
|
|
1
|
-
require 'dry/monads/maybe'
|
2
|
-
require 'dry/types/decorator'
|
3
|
-
|
4
|
-
module Dry
|
5
|
-
module Types
|
6
|
-
class Maybe
|
7
|
-
include Dry::Equalizer(:type, :options)
|
8
|
-
include Decorator
|
9
|
-
include Builder
|
10
|
-
include Dry::Monads::Maybe::Mixin
|
11
|
-
|
12
|
-
def call(input)
|
13
|
-
input.is_a?(Dry::Monads::Maybe) ? input : Maybe(type[input])
|
14
|
-
end
|
15
|
-
alias_method :[], :call
|
16
|
-
|
17
|
-
def try(input)
|
18
|
-
Result::Success.new(Maybe(type[input]))
|
19
|
-
end
|
20
|
-
|
21
|
-
def maybe?
|
22
|
-
true
|
23
|
-
end
|
24
|
-
|
25
|
-
def default(value)
|
26
|
-
if value.nil?
|
27
|
-
raise ArgumentError, "nil cannot be used as a default of a maybe type"
|
28
|
-
else
|
29
|
-
super
|
30
|
-
end
|
31
|
-
end
|
32
|
-
end
|
33
|
-
end
|
34
|
-
end
|
data/lib/dry/types/struct.rb
DELETED
@@ -1,25 +0,0 @@
|
|
1
|
-
require_relative 'hashify'
|
2
|
-
require 'dry/types/struct/class_interface'
|
3
|
-
|
4
|
-
module Dry
|
5
|
-
module Types
|
6
|
-
class Struct
|
7
|
-
extend ClassInterface
|
8
|
-
|
9
|
-
def initialize(attributes)
|
10
|
-
attributes.each { |key, value| instance_variable_set("@#{key}", value) }
|
11
|
-
end
|
12
|
-
|
13
|
-
def [](name)
|
14
|
-
public_send(name)
|
15
|
-
end
|
16
|
-
|
17
|
-
def to_hash
|
18
|
-
self.class.schema.keys.each_with_object({}) do |key, result|
|
19
|
-
result[key] = Hashify[self[key]]
|
20
|
-
end
|
21
|
-
end
|
22
|
-
alias_method :to_h, :to_hash
|
23
|
-
end
|
24
|
-
end
|
25
|
-
end
|
@@ -1,107 +0,0 @@
|
|
1
|
-
module Dry
|
2
|
-
module Types
|
3
|
-
class Struct
|
4
|
-
module ClassInterface
|
5
|
-
include Builder
|
6
|
-
|
7
|
-
attr_accessor :constructor
|
8
|
-
|
9
|
-
attr_accessor :equalizer
|
10
|
-
|
11
|
-
attr_writer :constructor_type
|
12
|
-
|
13
|
-
protected :constructor=, :equalizer=, :constructor_type=
|
14
|
-
|
15
|
-
def inherited(klass)
|
16
|
-
super
|
17
|
-
|
18
|
-
klass.equalizer = Equalizer.new(*schema.keys)
|
19
|
-
klass.constructor_type = constructor_type
|
20
|
-
klass.send(:include, klass.equalizer)
|
21
|
-
|
22
|
-
unless klass == Value
|
23
|
-
klass.constructor = Types['coercible.hash']
|
24
|
-
Types.register(Types.identifier(klass), klass)
|
25
|
-
end
|
26
|
-
|
27
|
-
klass.attributes({}) unless equal?(Struct)
|
28
|
-
end
|
29
|
-
|
30
|
-
def attribute(name, type)
|
31
|
-
attributes(name => type)
|
32
|
-
end
|
33
|
-
|
34
|
-
def attributes(new_schema)
|
35
|
-
check_schema_duplication(new_schema)
|
36
|
-
|
37
|
-
prev_schema = schema
|
38
|
-
|
39
|
-
@schema = prev_schema.merge(new_schema)
|
40
|
-
@constructor = Types['coercible.hash'].public_send(constructor_type, schema)
|
41
|
-
|
42
|
-
attr_reader(*new_schema.keys)
|
43
|
-
equalizer.instance_variable_get('@keys').concat(new_schema.keys)
|
44
|
-
|
45
|
-
self
|
46
|
-
end
|
47
|
-
|
48
|
-
def check_schema_duplication(new_schema)
|
49
|
-
shared_keys = new_schema.keys & schema.keys
|
50
|
-
|
51
|
-
fail RepeatedAttributeError, shared_keys.first if shared_keys.any?
|
52
|
-
end
|
53
|
-
private :check_schema_duplication
|
54
|
-
|
55
|
-
def constructor_type(type = nil)
|
56
|
-
if type
|
57
|
-
@constructor_type = type
|
58
|
-
else
|
59
|
-
@constructor_type || :strict
|
60
|
-
end
|
61
|
-
end
|
62
|
-
|
63
|
-
def schema
|
64
|
-
super_schema = superclass.respond_to?(:schema) ? superclass.schema : {}
|
65
|
-
super_schema.merge(@schema || {})
|
66
|
-
end
|
67
|
-
|
68
|
-
def new(attributes = default_attributes)
|
69
|
-
if attributes.instance_of?(self)
|
70
|
-
attributes
|
71
|
-
else
|
72
|
-
super(constructor[attributes])
|
73
|
-
end
|
74
|
-
rescue SchemaError, SchemaKeyError => error
|
75
|
-
raise StructError, "[#{self}.new] #{error}"
|
76
|
-
end
|
77
|
-
alias_method :call, :new
|
78
|
-
alias_method :[], :new
|
79
|
-
|
80
|
-
def default_attributes
|
81
|
-
schema.each_with_object({}) { |(name, type), result|
|
82
|
-
result[name] = type.default? ? type.evaluate : type[nil]
|
83
|
-
}
|
84
|
-
end
|
85
|
-
|
86
|
-
def try(input)
|
87
|
-
Result::Success.new(self[input])
|
88
|
-
rescue StructError => e
|
89
|
-
failure = Result::Failure.new(input, e.message)
|
90
|
-
block_given? ? yield(failure) : failure
|
91
|
-
end
|
92
|
-
|
93
|
-
def maybe?
|
94
|
-
false
|
95
|
-
end
|
96
|
-
|
97
|
-
def default?
|
98
|
-
false
|
99
|
-
end
|
100
|
-
|
101
|
-
def valid?(value)
|
102
|
-
self === value
|
103
|
-
end
|
104
|
-
end
|
105
|
-
end
|
106
|
-
end
|
107
|
-
end
|