definition 0.1.0.rc2 → 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
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