definition 0.1.0.rc2 → 0.1.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 3af4089033df18151f417df6667ab1f76b266d35728297abc1ead799bb25dab9
4
- data.tar.gz: 82e3b50fc7e7bdafd0317669c6960924627808f6ae19086a383ab91b3d3ead8e
3
+ metadata.gz: 99098a9f77beb85c63ac542c0903112ea45ac698ace223d92d6c88c6abf2d372
4
+ data.tar.gz: 314c23a060b6867edf1a8883eaa3b28ae2b45bfe3b197dab8f86d95d05383204
5
5
  SHA512:
6
- metadata.gz: ee6a8ef92b6844cbe89b9e18bccb10b12b4068f7726d73c1d24296873b61cf60dc2478da1948a8350017c7be868c466dce4a6a2482e2672a0959567f8fd8e7e5
7
- data.tar.gz: f8ed3f1933198bf18f750334fdd1662666c795dc2dbb80fbf84680c62dce436670ff8e4904bc32c77926e6ee0de0dc189eef304eac1a94f1c802c486b061f836
6
+ metadata.gz: 2876eb3d16401866eed9f6546b797d3824334d9aad5670d403b205c8995e7af9e63203ff4d4dd62a8156574a523943d0d572e777c2c934e6b0141367e38f62eb
7
+ data.tar.gz: a251ebc1e96ebfb89b0e49fb418e65cd051ab28a670d3dd2376d1cf4c4fe9992dab3fea8d02224241a82b885befdd668f4baab3ce43666a0f7219bd2d74ec9b7
@@ -12,3 +12,10 @@ jobs:
12
12
  - stage: linting
13
13
  rvm: ruby-head
14
14
  script: bundle exec rake rubocop
15
+ - stage: benchmark
16
+ script: bundle exec ruby benchmark/complex_example.rb
17
+ rvm: ruby-head
18
+ - script: bundle exec ruby benchmark/coercion.rb
19
+ rvm: ruby-head
20
+ - script: bundle exec ruby benchmark/validation_only.rb
21
+ rvm: ruby-head
data/README.md CHANGED
@@ -3,7 +3,7 @@
3
3
  [![Build Status](https://travis-ci.org/Goltergaul/definition.svg?branch=master)][travis]
4
4
  [![Gem Version](https://badge.fury.io/rb/definition.svg)][rubygems]
5
5
 
6
- Simple and composable validation and coercion of data structures. It also includes a ValueObject for convinience.
6
+ Simple and composable validation and coercion of data structures. It also includes a ValueObject for convenience.
7
7
 
8
8
  ## Installation
9
9
 
@@ -79,7 +79,7 @@ user[:username] # => "johndoe"
79
79
  user.username = "Alice" # => NoMethodError (ValueObjects are immutable)
80
80
  user[:username] = "Alice" # => FrozenError (ValueObjects are immutable)
81
81
 
82
- User.new(username: "johndoe") # => Definition::InvalidValueObjectError: hash does not include :last_name
82
+ User.new(username: "johndoe") # => Definition::InvalidValueObjectError: hash does not include :password
83
83
  ```
84
84
 
85
85
  Value objects delegate all calls to the output value of the defined definition,
@@ -0,0 +1,71 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "bundler/inline"
4
+
5
+ gemfile do
6
+ source "https://rubygems.org"
7
+ gem "definition"
8
+ gem "dry-validation"
9
+ gem "awesome_print"
10
+ gem "benchmark-ips"
11
+ gem "pry"
12
+ end
13
+
14
+ DryTimeCoercionType = Dry::Types["strict.string"].constructor do |value|
15
+ if value.is_a?(Integer)
16
+ Time.at(value).utc
17
+ else
18
+ value
19
+ end
20
+ end
21
+ DrySchema = Dry::Validation.Params do
22
+ configure do
23
+ config.type_specs = true
24
+ end
25
+
26
+ required(:name, :string).value(type?: String)
27
+ required(:time, DryTimeCoercionType).value(type?: Time)
28
+ end
29
+
30
+ DefinitionSchema = Definition.Keys do
31
+ required(:name, Definition.Type(String))
32
+ required(:time, Definition.Lambda(:time) do |value|
33
+ conform_with(Time.at(value).utc) if value.is_a?(Integer)
34
+ end)
35
+ end
36
+
37
+ puts "Benchmark with valid input data:"
38
+ valid_data = { name: "test", time: Time.now.to_i }
39
+ ap DefinitionSchema.conform(valid_data).value
40
+ ap DrySchema.call(valid_data)
41
+ Benchmark.ips do |x|
42
+ x.config(time: 5, warmup: 2)
43
+
44
+ x.report("definition") do
45
+ DefinitionSchema.conform(valid_data).value
46
+ end
47
+
48
+ x.report("dry-validation") do
49
+ DrySchema.call(valid_data)
50
+ end
51
+
52
+ x.compare!
53
+ end
54
+
55
+ puts "Benchmark with invalid input data:"
56
+ invalid_data = { name: 1, time: Time.now.to_s }
57
+ ap DefinitionSchema.conform(invalid_data).error_message
58
+ ap DrySchema.call(invalid_data).errors
59
+ Benchmark.ips do |x|
60
+ x.config(time: 5, warmup: 2)
61
+
62
+ x.report("definition") do
63
+ DefinitionSchema.conform(invalid_data)
64
+ end
65
+
66
+ x.report("dry-validation") do
67
+ DrySchema.call(invalid_data)
68
+ end
69
+
70
+ x.compare!
71
+ end
@@ -0,0 +1,175 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "bundler/inline"
4
+
5
+ gemfile do
6
+ source "https://rubygems.org"
7
+ gem "definition"
8
+ gem "dry-validation"
9
+ gem "awesome_print"
10
+ gem "benchmark-ips"
11
+ gem "pry"
12
+ end
13
+
14
+ DryTimeCoercionType = Dry::Types["strict.string"].constructor do |value|
15
+ if value.is_a?(Integer)
16
+ Time.at(value / 1000.0).utc
17
+ else
18
+ value
19
+ end
20
+ end
21
+ DrySchema = Dry::Validation.Params do # rubocop:disable Metrics/BlockLength
22
+ configure do
23
+ config.type_specs = true
24
+ end
25
+
26
+ required(:data).schema do
27
+ required(:type, :string).value(Dry::Types["strict.string"].enum("article"))
28
+ required(:id, :string).value(type?: String)
29
+ required(:attributes).schema do
30
+ required(:title, :string).filled(max_size?: 1000)
31
+ required(:body, :string).filled(max_size?: 1000)
32
+ required(:publish_date, DryTimeCoercionType).value(type?: Time)
33
+ end
34
+
35
+ required(:relationships).schema do
36
+ required(:author).schema do
37
+ required(:data).schema do
38
+ required(:id, :string).value(type?: String)
39
+ required(:type, :string).value(Dry::Types["strict.string"].enum("people"))
40
+ end
41
+ end
42
+ optional(:comments).schema do
43
+ required(:data).each do
44
+ schema do
45
+ required(:id, :string).value(type?: String)
46
+ required(:type, :string).value(Dry::Types["strict.string"].enum("comment"))
47
+ end
48
+ end
49
+ end
50
+ end
51
+ end
52
+ end
53
+
54
+ MAX_LENGTH = Definition.Lambda(:max_length) do |value|
55
+ conform_with(value) if value.size <= 1000
56
+ end
57
+ MAX_STRING_LENGTH = Definition.And(
58
+ Definition.Type(String),
59
+ MAX_LENGTH
60
+ )
61
+ MILLISECONDS_TIME = Definition.Lambda(:milliseconds_time) do |v|
62
+ conform_with(Time.at(v / 1000.0).utc) if v.is_a?(Integer)
63
+ end
64
+ DefinitionSchema = Definition.Keys do
65
+ required(:data, Definition.Keys do
66
+ required :type, Definition.Enum("article")
67
+ required :id, Definition.Type(String)
68
+ required(:attributes, Definition.Keys do
69
+ required :title, MAX_STRING_LENGTH
70
+ required :body, MAX_STRING_LENGTH
71
+ required :publish_date, MILLISECONDS_TIME
72
+ end)
73
+
74
+ required(:relationships, Definition.Keys do
75
+ required(:author, Definition.Keys do
76
+ required(:data, Definition.Keys do
77
+ required :id, Definition.Type(String)
78
+ required :type, Definition.Enum("people")
79
+ end)
80
+ end)
81
+ optional(:comments, Definition.Keys do
82
+ required(:data, Definition.Each(
83
+ Definition.Keys do
84
+ required :id, Definition.Type(String)
85
+ required :type, Definition.Enum("comment")
86
+ end
87
+ ))
88
+ end)
89
+ end)
90
+ end)
91
+ end
92
+
93
+ puts "Benchmark with valid input data:"
94
+ valid_data = {
95
+ "data": {
96
+ "type": "article",
97
+ "id": "1",
98
+ "attributes": {
99
+ "title": "JSON:API paints my bikeshed!",
100
+ "body": "The shortest article. Ever.",
101
+ "publish_date": Time.utc(2018).to_i * 1000
102
+ },
103
+ "relationships": {
104
+ "author": {
105
+ "data": { "id": "42", "type": "people" }
106
+ },
107
+ "comments": {
108
+ "data": [
109
+ { "id": "1", "type": "comment" },
110
+ { "id": "2", "type": "comment" }
111
+ ]
112
+ }
113
+ }
114
+ }
115
+ }
116
+ ap DefinitionSchema.conform(valid_data).value
117
+ ap DrySchema.call(valid_data)
118
+ raise unless DefinitionSchema.conform(valid_data).passed?
119
+ raise unless DrySchema.call(valid_data).success?
120
+
121
+ Benchmark.ips do |x|
122
+ x.config(time: 5, warmup: 2)
123
+
124
+ x.report("definition") do
125
+ DefinitionSchema.conform(valid_data)
126
+ end
127
+
128
+ x.report("dry-validation") do
129
+ DrySchema.call(valid_data)
130
+ end
131
+
132
+ x.compare!
133
+ end
134
+
135
+ puts "Benchmark with invalid input data:"
136
+ invalid_data = {
137
+ "data": {
138
+ "type": "article",
139
+ "id": "1",
140
+ "attributes": {
141
+ "title": "JSON:API paints my bikeshed!",
142
+ "body": "The shortest article. Ever.",
143
+ "publish_date": Time.utc(2018).to_s
144
+ },
145
+ "relationships": {
146
+ "author": {
147
+ "data": { "id": "42", "type": "people" }
148
+ },
149
+ "comments": {
150
+ "data": [
151
+ { "id": "1", "type": "comment" },
152
+ { "id": "2", "type": "post" }
153
+ ]
154
+ }
155
+ }
156
+ }
157
+ }
158
+ ap DefinitionSchema.conform(invalid_data).error_message
159
+ ap DrySchema.call(invalid_data).errors
160
+ raise if DefinitionSchema.conform(invalid_data).passed?
161
+ raise if DrySchema.call(invalid_data).success?
162
+
163
+ Benchmark.ips do |x|
164
+ x.config(time: 5, warmup: 2)
165
+
166
+ x.report("definition") do
167
+ DefinitionSchema.conform(invalid_data)
168
+ end
169
+
170
+ x.report("dry-validation") do
171
+ DrySchema.call(invalid_data)
172
+ end
173
+
174
+ x.compare!
175
+ end
@@ -0,0 +1,61 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "bundler/inline"
4
+
5
+ gemfile do
6
+ source "https://rubygems.org"
7
+ gem "definition"
8
+ gem "dry-validation"
9
+ gem "awesome_print"
10
+ gem "benchmark-ips"
11
+ end
12
+
13
+ DrySchema = Dry::Validation.Params do
14
+ configure do
15
+ config.type_specs = true
16
+ end
17
+
18
+ required(:name, :string).value(type?: String)
19
+ required(:time, :time).value(type?: String)
20
+ end
21
+
22
+ DefinitionSchema = Definition.Keys do
23
+ required(:name, Definition.Type(String))
24
+ required(:time, Definition.Type(Time))
25
+ end
26
+
27
+ puts "Benchmark with valid input data:"
28
+ valid_data = { name: "test", time: Time.now }
29
+ ap DefinitionSchema.conform(valid_data).value
30
+ ap DrySchema.call(valid_data)
31
+ Benchmark.ips do |x|
32
+ x.config(time: 5, warmup: 2)
33
+
34
+ x.report("definition") do
35
+ DefinitionSchema.conform(valid_data)
36
+ end
37
+
38
+ x.report("dry-validation") do
39
+ DrySchema.call(valid_data)
40
+ end
41
+
42
+ x.compare!
43
+ end
44
+
45
+ puts "Benchmark with invalid input data:"
46
+ invalid_data = { name: 1, time: Time.now.to_s }
47
+ ap DefinitionSchema.conform(invalid_data).error_message
48
+ ap DrySchema.call(invalid_data).errors
49
+ Benchmark.ips do |x|
50
+ x.config(time: 5, warmup: 2)
51
+
52
+ x.report("definition") do
53
+ DefinitionSchema.conform(invalid_data)
54
+ end
55
+
56
+ x.report("dry-validation") do
57
+ DrySchema.call(invalid_data)
58
+ end
59
+
60
+ x.compare!
61
+ end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Definition
4
- VERSION = "0.1.0.rc2"
4
+ VERSION = "0.1.0"
5
5
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: definition
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0.rc2
4
+ version: 0.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Dominik Goltermann
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2019-01-02 00:00:00.000000000 Z
11
+ date: 2019-01-12 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: approvals
@@ -236,6 +236,9 @@ files:
236
236
  - Guardfile
237
237
  - README.md
238
238
  - Rakefile
239
+ - benchmark/coercion.rb
240
+ - benchmark/complex_example.rb
241
+ - benchmark/validation_only.rb
239
242
  - bin/console
240
243
  - bin/setup
241
244
  - definition.gemspec
@@ -269,9 +272,9 @@ required_ruby_version: !ruby/object:Gem::Requirement
269
272
  version: '0'
270
273
  required_rubygems_version: !ruby/object:Gem::Requirement
271
274
  requirements:
272
- - - ">"
275
+ - - ">="
273
276
  - !ruby/object:Gem::Version
274
- version: 1.3.1
277
+ version: '0'
275
278
  requirements: []
276
279
  rubyforge_project:
277
280
  rubygems_version: 2.7.6