plumb 0.0.9 → 0.0.11
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/README.md +23 -17
- data/examples/concurrent_downloads.rb +1 -1
- data/examples/csv_stream.rb +1 -1
- data/lib/plumb/attribute_value_match.rb +25 -0
- data/lib/plumb/composable.rb +20 -6
- data/lib/plumb/json_schema_visitor.rb +29 -14
- data/lib/plumb/schema.rb +5 -0
- data/lib/plumb/types.rb +2 -12
- data/lib/plumb/version.rb +1 -1
- metadata +3 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 970d29a4515fd3e9938a93474cee93d37ee90e7b197c004d4a6e2fd9f36fef4a
|
4
|
+
data.tar.gz: ed7e89f47023ee9d1cdf53b3c39758ff69f0c0cb4399a4b972a4ad670f9c4cfd
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 066e9e2d5e06c19286600e21bbe85da7304c87156241e7eae79c2dcc4abb30a370416dd4cfe343d66535521848b25c4e348a1bacc7f7aff71c5ab790c6afeae4
|
7
|
+
data.tar.gz: b6064b236ec5656b648bcc576c7ca0dbccfc172ec8615eba32e98a157ba2600ce282ab1e154b07a5be47999dcda2838698c639d51651b6e41e49f7dce6058d71
|
data/README.md
CHANGED
@@ -328,6 +328,28 @@ type.resolve(['a', 'a', 'b']) # Valid
|
|
328
328
|
type.resolve(['a', 'x', 'b']) # Failure
|
329
329
|
```
|
330
330
|
|
331
|
+
### `#with`
|
332
|
+
|
333
|
+
The `#with` helper matches attributes of the object with values, using `#===`.
|
334
|
+
|
335
|
+
```ruby
|
336
|
+
LimitedArray = Types::Array[String].with(size: 10)
|
337
|
+
LimitedString = Types::String.with(size: 10)
|
338
|
+
LimitedSet = Types::Any[Set].with(size: 10)
|
339
|
+
```
|
340
|
+
|
341
|
+
The size is matched via `#===`, so ranges also work.
|
342
|
+
|
343
|
+
```ruby
|
344
|
+
Password = Types::String.with(bytesize: 10..20)
|
345
|
+
```
|
346
|
+
|
347
|
+
The helper accepts multiple attribute/valye pairs
|
348
|
+
|
349
|
+
```ruby
|
350
|
+
JoeBloggs = Types::Any[User].with(first_name: 'Joe', last_name: 'Bloggs')
|
351
|
+
```
|
352
|
+
|
331
353
|
#### `#transform`
|
332
354
|
|
333
355
|
Transform value. Requires specifying the resulting type of the value after transformation.
|
@@ -588,23 +610,7 @@ The opposite of `#options`, this policy validates that the value _is not_ includ
|
|
588
610
|
Name = Types::String.policy(excluded_from: ['Joe', 'Joan'])
|
589
611
|
```
|
590
612
|
|
591
|
-
####
|
592
|
-
|
593
|
-
Works for any value that responds to `#size` and validates that the value's size matches the argument.
|
594
|
-
|
595
|
-
```ruby
|
596
|
-
LimitedArray = Types::Array[String].policy(size: 10)
|
597
|
-
LimitedString = Types::String.policy(size: 10)
|
598
|
-
LimitedSet = Types::Any[Set].policy(size: 10)
|
599
|
-
```
|
600
|
-
|
601
|
-
The size is matched via `#===`, so ranges also work.
|
602
|
-
|
603
|
-
```ruby
|
604
|
-
Password = Types::String.policy(size: 10..20)
|
605
|
-
```
|
606
|
-
|
607
|
-
#### `:split` (strings only)
|
613
|
+
#### :split` (strings only)
|
608
614
|
|
609
615
|
Splits string values by a separator (default: `,`).
|
610
616
|
|
@@ -67,7 +67,7 @@ module Types
|
|
67
67
|
end
|
68
68
|
|
69
69
|
###################################
|
70
|
-
# Program 1:
|
70
|
+
# Program 1: idempotent download of images from the internet
|
71
71
|
# If not present in the cache, images are downloaded and written to the cache.
|
72
72
|
# Otherwise images are listed directly from the cache (files on disk).
|
73
73
|
###################################
|
data/examples/csv_stream.rb
CHANGED
@@ -10,7 +10,7 @@ module Types
|
|
10
10
|
include Plumb::Types
|
11
11
|
|
12
12
|
# Open a File
|
13
|
-
# ex. file =
|
13
|
+
# ex. file = OpenFile.parse('./files/data.csv') # => File
|
14
14
|
OpenFile = String
|
15
15
|
.check('no file for that path') { |s| ::File.exist?(s) }
|
16
16
|
.build(::File)
|
@@ -0,0 +1,25 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Plumb
|
4
|
+
class AttributeValueMatch
|
5
|
+
include Composable
|
6
|
+
|
7
|
+
attr_reader :type, :attr_name, :value
|
8
|
+
|
9
|
+
def initialize(type, attr_name, value)
|
10
|
+
@type = type
|
11
|
+
@attr_name = attr_name
|
12
|
+
@value = value
|
13
|
+
@error = "must have attribute #{attr_name} === #{value.inspect}"
|
14
|
+
freeze
|
15
|
+
end
|
16
|
+
|
17
|
+
def metadata = type.metadata
|
18
|
+
|
19
|
+
def call(result)
|
20
|
+
return result if value === result.value.public_send(attr_name)
|
21
|
+
|
22
|
+
result.invalid(errors: @error)
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
data/lib/plumb/composable.rb
CHANGED
@@ -273,15 +273,16 @@ module Plumb
|
|
273
273
|
class Node
|
274
274
|
include Composable
|
275
275
|
|
276
|
-
attr_reader :node_name, :type, :
|
276
|
+
attr_reader :node_name, :type, :args
|
277
277
|
|
278
|
-
def initialize(node_name, type,
|
278
|
+
def initialize(node_name, type, args = BLANK_HASH)
|
279
279
|
@node_name = node_name
|
280
280
|
@type = type
|
281
|
-
@
|
281
|
+
@args = args
|
282
282
|
freeze
|
283
283
|
end
|
284
284
|
|
285
|
+
def metadata = type.metadata
|
285
286
|
def call(result) = type.call(result)
|
286
287
|
end
|
287
288
|
|
@@ -291,10 +292,22 @@ module Plumb
|
|
291
292
|
# Ex. Types::Boolean is a compoition of Types::True | Types::False, but we want to treat it as a single node.
|
292
293
|
#
|
293
294
|
# @param node_name [Symbol]
|
294
|
-
# @param
|
295
|
+
# @param args [Hash]
|
295
296
|
# @return [Node]
|
296
|
-
def as_node(node_name,
|
297
|
-
Node.new(node_name, self,
|
297
|
+
def as_node(node_name, args = BLANK_HASH)
|
298
|
+
Node.new(node_name, self, args)
|
299
|
+
end
|
300
|
+
|
301
|
+
# Check attributes of an object against values, using #===
|
302
|
+
# @example
|
303
|
+
# type = Types::Array.with(size: 1..10)
|
304
|
+
# type = Types::String.with(bytesize: 1..10)
|
305
|
+
#
|
306
|
+
# @param attrs [Hash]
|
307
|
+
def with(attrs)
|
308
|
+
attrs.reduce(self) do |t, (name, value)|
|
309
|
+
t >> AttributeValueMatch.new(t, name, value)
|
310
|
+
end
|
298
311
|
end
|
299
312
|
|
300
313
|
# Register a policy for this step.
|
@@ -425,6 +438,7 @@ module Plumb
|
|
425
438
|
end
|
426
439
|
|
427
440
|
require 'plumb/deferred'
|
441
|
+
require 'plumb/attribute_value_match'
|
428
442
|
require 'plumb/transform'
|
429
443
|
require 'plumb/policy'
|
430
444
|
require 'plumb/build'
|
@@ -138,30 +138,41 @@ module Plumb
|
|
138
138
|
end
|
139
139
|
end
|
140
140
|
|
141
|
+
on(:attribute_value_match) do |node, props|
|
142
|
+
method_name = :"visit_with_#{node.attr_name}_attribute"
|
143
|
+
if respond_to?(method_name)
|
144
|
+
send(method_name, node, props)
|
145
|
+
else
|
146
|
+
props
|
147
|
+
end
|
148
|
+
end
|
149
|
+
|
141
150
|
on(:options_policy) do |node, props|
|
142
151
|
props.merge(ENUM => node.arg)
|
143
152
|
end
|
144
153
|
|
145
|
-
on(:
|
146
|
-
opts =
|
147
|
-
|
154
|
+
on(:with_size_attribute) do |node, props|
|
155
|
+
opts = visit(node.type)
|
156
|
+
value = node.value
|
157
|
+
|
158
|
+
case opts[TYPE]
|
148
159
|
when 'array'
|
149
|
-
case
|
160
|
+
case value
|
150
161
|
when Range
|
151
|
-
opts[MIN_ITEMS] =
|
152
|
-
opts[MAX_ITEMS] =
|
162
|
+
opts[MIN_ITEMS] = value.min if value.begin
|
163
|
+
opts[MAX_ITEMS] = value.max if value.end
|
153
164
|
when Numeric
|
154
|
-
opts[MIN_ITEMS] =
|
155
|
-
opts[MAX_ITEMS] =
|
165
|
+
opts[MIN_ITEMS] = value
|
166
|
+
opts[MAX_ITEMS] = value
|
156
167
|
end
|
157
168
|
when 'string'
|
158
|
-
case
|
169
|
+
case value
|
159
170
|
when Range
|
160
|
-
opts[MIN_LENGTH] =
|
161
|
-
opts[MAX_LENGTH] =
|
171
|
+
opts[MIN_LENGTH] = value.min if value.begin
|
172
|
+
opts[MAX_LENGTH] = value.max if value.end
|
162
173
|
when Numeric
|
163
|
-
opts[MIN_LENGTH] =
|
164
|
-
opts[MAX_LENGTH] =
|
174
|
+
opts[MIN_LENGTH] = value
|
175
|
+
opts[MAX_LENGTH] = value
|
165
176
|
end
|
166
177
|
end
|
167
178
|
|
@@ -242,7 +253,11 @@ module Plumb
|
|
242
253
|
opts = visit(element.class)
|
243
254
|
if element.is_a?(::Numeric)
|
244
255
|
opts[MINIMUM] = node.min if node.begin
|
245
|
-
|
256
|
+
if node.end
|
257
|
+
max = node.end
|
258
|
+
max -= 1 if node.exclude_end?
|
259
|
+
opts[MAXIMUM] = max
|
260
|
+
end
|
246
261
|
end
|
247
262
|
props.merge(opts)
|
248
263
|
end
|
data/lib/plumb/schema.rb
CHANGED
data/lib/plumb/types.rb
CHANGED
@@ -7,6 +7,7 @@ require 'time'
|
|
7
7
|
|
8
8
|
module Plumb
|
9
9
|
# Define core policies
|
10
|
+
#
|
10
11
|
# Allowed options for an array type.
|
11
12
|
# It validates that each element is in the options array.
|
12
13
|
# Usage:
|
@@ -43,17 +44,6 @@ module Plumb
|
|
43
44
|
end
|
44
45
|
end
|
45
46
|
|
46
|
-
# Validate #size against a number or any object that responds to #===.
|
47
|
-
# This works with any type that repsonds to #size.
|
48
|
-
# Usage:
|
49
|
-
# type = Types::String.policy(size: 10)
|
50
|
-
# type = Types::Integer.policy(size: 1..10)
|
51
|
-
# type = Types::Array.policy(size: 1..)
|
52
|
-
# type = Types::Any[Set].policy(size: 1..)
|
53
|
-
policy :size, for_type: :size do |type, size|
|
54
|
-
type.check("must be of size #{size}") { |v| size === v.size }
|
55
|
-
end
|
56
|
-
|
57
47
|
# Validate that an object is not #empty? nor #nil?
|
58
48
|
# Usage:
|
59
49
|
# Types::String.present
|
@@ -181,7 +171,7 @@ module Plumb
|
|
181
171
|
end
|
182
172
|
|
183
173
|
module Lax
|
184
|
-
NUMBER_EXPR = /^\d{1,3}(
|
174
|
+
NUMBER_EXPR = /^\d{1,3}(?:,?\d{3})*(?:\.\d+)?$/
|
185
175
|
|
186
176
|
String = Types::String \
|
187
177
|
| Types::Decimal.transform(::String) { |v| v.to_s('F') } \
|
data/lib/plumb/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: plumb
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.11
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Ismael Celis
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2025-03-14 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bigdecimal
|
@@ -65,6 +65,7 @@ files:
|
|
65
65
|
- lib/plumb/and.rb
|
66
66
|
- lib/plumb/any_class.rb
|
67
67
|
- lib/plumb/array_class.rb
|
68
|
+
- lib/plumb/attribute_value_match.rb
|
68
69
|
- lib/plumb/attributes.rb
|
69
70
|
- lib/plumb/build.rb
|
70
71
|
- lib/plumb/composable.rb
|