nrser 0.0.23 → 0.0.24
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/lib/nrser/enumerable.rb +1 -1
- data/lib/nrser/refinements/array.rb +28 -0
- data/lib/nrser/types/is_a.rb +2 -2
- data/lib/nrser/types/paths.rb +83 -0
- data/lib/nrser/types/type.rb +24 -5
- data/lib/nrser/types.rb +82 -22
- data/lib/nrser/version.rb +1 -1
- data/spec/nrser/enumerable_spec.rb +14 -0
- data/spec/nrser/types_spec.rb +22 -0
- metadata +3 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: ad84454dbdd85a4a86dbb940a0901cafe0effaef
|
4
|
+
data.tar.gz: 9992915527ce7f7749aac2d9bdf319a05507fd23
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 995db23a4d353e6a54fec4480e3d17175b99efb75a0a08cc0583a3b166fa1153a26ce58b66d2b592306a17d495ca3544a805a06a03fb06516337f072ee22eb91
|
7
|
+
data.tar.gz: 47488b4ca3a7655f5264578a6e9283b04e2e1148093c72ec032cbc03720f098d6e7531cd44ccc1e20f9ec3e4ea063a905fb4f4699b6793042a816e0a7f5d6ca7
|
data/lib/nrser/enumerable.rb
CHANGED
@@ -115,7 +115,7 @@ module NRSER
|
|
115
115
|
key = block.call element
|
116
116
|
|
117
117
|
if result.key? key
|
118
|
-
raise NRSER::ConflictError.
|
118
|
+
raise NRSER::ConflictError.new NRSER.dedent <<-END
|
119
119
|
Key #{ key.inspect } is already in results with value:
|
120
120
|
|
121
121
|
#{ result[key].pretty_inspect }
|
@@ -13,5 +13,33 @@ module NRSER
|
|
13
13
|
NRSER.rest self
|
14
14
|
end # #rest
|
15
15
|
|
16
|
+
|
17
|
+
# Returns a lambda that calls accepts a single arg and calls `#dig` on it
|
18
|
+
# with the elements of *this* array as arguments.
|
19
|
+
#
|
20
|
+
# @example
|
21
|
+
# list = [{id: 1, name: "Neil"}, {id: 2, name: "Mica"}]
|
22
|
+
# list.to_h_by &[:id].digger
|
23
|
+
# # => {
|
24
|
+
# # 1 => {id: 1, name: "Neil"},
|
25
|
+
# # 2 => {id: 2, name: "Mica"},
|
26
|
+
# # }
|
27
|
+
#
|
28
|
+
# @todo
|
29
|
+
# I wanted to use `#to_proc` so that you could use `&[:id]`, but unary
|
30
|
+
# `&` doesn't invoke refinements, and I don't really want to monkey-patch
|
31
|
+
# anything, especially something as core as `#to_proc` and `Array`.
|
32
|
+
#
|
33
|
+
# @return [Proc]
|
34
|
+
# Lambda proc that accepts a single argument and calls `#dig` with this
|
35
|
+
# array's contents as the `#dig` arguments.
|
36
|
+
#
|
37
|
+
def digger
|
38
|
+
->(digable) {
|
39
|
+
digable.dig *self
|
40
|
+
}
|
41
|
+
end # #digable
|
42
|
+
|
43
|
+
|
16
44
|
end # refine ::Array
|
17
45
|
end # NRSER
|
data/lib/nrser/types/is_a.rb
CHANGED
@@ -0,0 +1,83 @@
|
|
1
|
+
# Requirements
|
2
|
+
# =======================================================================
|
3
|
+
|
4
|
+
# stdlib
|
5
|
+
require 'pathname'
|
6
|
+
|
7
|
+
# gems
|
8
|
+
|
9
|
+
# package
|
10
|
+
require_relative './is_a'
|
11
|
+
require_relative './where'
|
12
|
+
require_relative './combinators'
|
13
|
+
|
14
|
+
|
15
|
+
# Refinements
|
16
|
+
# =======================================================================
|
17
|
+
|
18
|
+
require 'nrser/refinements'
|
19
|
+
using NRSER
|
20
|
+
|
21
|
+
|
22
|
+
# Declarations
|
23
|
+
# =======================================================================
|
24
|
+
|
25
|
+
module NRSER; end
|
26
|
+
|
27
|
+
|
28
|
+
# Definitions
|
29
|
+
# =======================================================================
|
30
|
+
|
31
|
+
module NRSER::Types
|
32
|
+
|
33
|
+
# A {Pathname} type that provides a `from_s`
|
34
|
+
PATHNAME = is_a \
|
35
|
+
Pathname,
|
36
|
+
name: 'PathnameType',
|
37
|
+
from_s: ->(string) { Pathname.new string }
|
38
|
+
|
39
|
+
|
40
|
+
# A type satisfied by a {Pathname} instance that's not empty (meaning it's
|
41
|
+
# string representation is not empty).
|
42
|
+
NON_EMPTY_PATHNAME = intersection \
|
43
|
+
PATHNAME,
|
44
|
+
where { |value| value.to_s.length > 0 },
|
45
|
+
name: 'NonEmptyPathnameType'
|
46
|
+
|
47
|
+
|
48
|
+
PATH = union non_empty_str, NON_EMPTY_PATHNAME, name: 'Path'
|
49
|
+
|
50
|
+
|
51
|
+
# Eigenclass (Singleton Class)
|
52
|
+
# ========================================================================
|
53
|
+
#
|
54
|
+
class << self
|
55
|
+
|
56
|
+
def pathname **options
|
57
|
+
if options.empty?
|
58
|
+
PATHNAME
|
59
|
+
else
|
60
|
+
is_a \
|
61
|
+
Pathname,
|
62
|
+
name: 'PathnameType',
|
63
|
+
from_s: ->(string) { Pathname.new string },
|
64
|
+
**options
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
#
|
69
|
+
#
|
70
|
+
# @return [NRSER::Types::Type]
|
71
|
+
#
|
72
|
+
def path **options
|
73
|
+
if options.empty?
|
74
|
+
PATH
|
75
|
+
else
|
76
|
+
union non_empty_str, NON_EMPTY_PATHNAME, **options
|
77
|
+
end
|
78
|
+
end # #path
|
79
|
+
|
80
|
+
end # class << self (Eigenclass)
|
81
|
+
|
82
|
+
end # module NRSER::Types
|
83
|
+
|
data/lib/nrser/types/type.rb
CHANGED
@@ -7,10 +7,29 @@ module NRSER::Types
|
|
7
7
|
name.split('::').last
|
8
8
|
end
|
9
9
|
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
10
|
+
|
11
|
+
# Constructor
|
12
|
+
# =====================================================================
|
13
|
+
|
14
|
+
# Instantiate a new `NRSER::Types::Type`.
|
15
|
+
#
|
16
|
+
# @param [nil | String] name:
|
17
|
+
# Name that will be used when displaying the type, or `nil` to use a
|
18
|
+
# default generated name.
|
19
|
+
#
|
20
|
+
# @param [nil | #call] from_s:
|
21
|
+
# Callable that will be passed a {String} and should return an object
|
22
|
+
# that satisfies the type if it possible to create one.
|
23
|
+
#
|
24
|
+
# The returned value *will* be checked against the type, so returning a
|
25
|
+
# value that doesn't satisfy will result in a {TypeError} being raised
|
26
|
+
# by {#from_s}.
|
27
|
+
#
|
28
|
+
def initialize name: nil, from_s: nil
|
29
|
+
@name = name
|
30
|
+
@from_s = from_s
|
31
|
+
end # #initialize
|
32
|
+
|
14
33
|
|
15
34
|
def name
|
16
35
|
@name || default_name
|
@@ -52,7 +71,7 @@ module NRSER::Types
|
|
52
71
|
raise NoMethodError, "#from_s not defined"
|
53
72
|
end
|
54
73
|
|
55
|
-
check @from_s.(s)
|
74
|
+
check @from_s.call( s )
|
56
75
|
end
|
57
76
|
|
58
77
|
def has_from_s?
|
data/lib/nrser/types.rb
CHANGED
@@ -1,19 +1,68 @@
|
|
1
|
+
# Requirements
|
2
|
+
# =======================================================================
|
3
|
+
|
4
|
+
# Stdlib
|
5
|
+
# ---------------------------------------------------------------------
|
6
|
+
|
7
|
+
# TODO Not sure if this needs to be here... can't find any usage of it in
|
8
|
+
# quick searches, but I don't want to remove it now.
|
1
9
|
require 'pp'
|
2
10
|
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
11
|
+
# Deps
|
12
|
+
# ---------------------------------------------------------------------
|
13
|
+
|
14
|
+
# Package
|
15
|
+
# ---------------------------------------------------------------------
|
16
|
+
|
17
|
+
# Abstract infrastructure for type creation - stuff that doesn't define any
|
18
|
+
# concrete type instances.
|
19
|
+
#
|
20
|
+
# Files that define concrete type instances on load (usually as module
|
21
|
+
# constants, which I'm still questioning a bit as a design because of the
|
22
|
+
# uncontrollable mutability of Ruby and the importance of type checks)
|
23
|
+
# need to be required in the "Post-Processing" section at the bottom.
|
24
|
+
#
|
25
|
+
require_relative './types/type'
|
26
|
+
require_relative './types/is'
|
27
|
+
require_relative './types/is_a'
|
28
|
+
require_relative './types/where'
|
29
|
+
require_relative './types/combinators'
|
30
|
+
require_relative './types/maybe'
|
31
|
+
require_relative './types/attrs'
|
32
|
+
require_relative './types/responds'
|
33
|
+
|
12
34
|
|
35
|
+
# Refinements
|
36
|
+
# =======================================================================
|
37
|
+
|
38
|
+
require 'nrser/refinements'
|
13
39
|
using NRSER
|
14
|
-
|
40
|
+
|
41
|
+
|
42
|
+
# Stuff to help you define, test, check and match types in Ruby.
|
43
|
+
#
|
15
44
|
module NRSER::Types
|
16
|
-
|
45
|
+
|
46
|
+
# Make a {NRSER::Types::Type} from a value.
|
47
|
+
#
|
48
|
+
# If the `value` argument is...
|
49
|
+
#
|
50
|
+
# - a {NRSER::Types::Type}, it is returned.
|
51
|
+
#
|
52
|
+
# - a {Class}, a new {NRSER::Types::IsA} matching that class is returned.
|
53
|
+
#
|
54
|
+
# This allows things like
|
55
|
+
#
|
56
|
+
# NRSER::Types.check 's', String
|
57
|
+
# NRSER::Types.match 's', String, ->(s) { ... }
|
58
|
+
#
|
59
|
+
# - anything else, a new {NRSER::Types::Is} matching that value is
|
60
|
+
# returned.
|
61
|
+
#
|
62
|
+
# @param [Object] value
|
63
|
+
#
|
64
|
+
# @return [NRSER::Types::Type]
|
65
|
+
#
|
17
66
|
def self.make value
|
18
67
|
if value.is_a? NRSER::Types::Type
|
19
68
|
value
|
@@ -24,15 +73,18 @@ module NRSER::Types
|
|
24
73
|
end
|
25
74
|
end
|
26
75
|
|
76
|
+
|
27
77
|
# raise an error if value doesn't match type.
|
28
78
|
def self.check value, type
|
29
79
|
make(type).check value
|
30
80
|
end
|
31
81
|
|
82
|
+
|
32
83
|
def self.test value, type
|
33
84
|
make(type).test value
|
34
85
|
end
|
35
86
|
|
87
|
+
|
36
88
|
def self.match value, *clauses
|
37
89
|
if clauses.empty?
|
38
90
|
raise ArgumentError.new NRSER.dedent <<-END
|
@@ -84,7 +136,8 @@ module NRSER::Types
|
|
84
136
|
#{ enum.map {|type, expression| "\n #{ type.inspect }"} }
|
85
137
|
|
86
138
|
END
|
87
|
-
end
|
139
|
+
end # .match
|
140
|
+
|
88
141
|
|
89
142
|
# make a type instance from a object representation that can come from
|
90
143
|
# a YAML or JSON declaration.
|
@@ -98,15 +151,22 @@ module NRSER::Types
|
|
98
151
|
|
99
152
|
},
|
100
153
|
}
|
101
|
-
end
|
154
|
+
end # .from_repr
|
155
|
+
|
102
156
|
end # NRSER::Types
|
103
157
|
|
104
|
-
|
105
|
-
#
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
158
|
+
|
159
|
+
# Post-Processing
|
160
|
+
# =======================================================================
|
161
|
+
#
|
162
|
+
# Files that define constants that need the proceeding infrastructure.
|
163
|
+
#
|
164
|
+
|
165
|
+
require_relative './types/any'
|
166
|
+
require_relative './types/booleans'
|
167
|
+
require_relative './types/numbers'
|
168
|
+
require_relative './types/strings'
|
169
|
+
require_relative './types/symbol'
|
170
|
+
require_relative './types/array'
|
171
|
+
require_relative './types/hash'
|
172
|
+
require_relative './types/paths'
|
data/lib/nrser/version.rb
CHANGED
@@ -93,5 +93,19 @@ describe "NRSER Enumerable Methods" do
|
|
93
93
|
end # NRSER.method(:find_only)
|
94
94
|
|
95
95
|
|
96
|
+
describe NRSER.method(:to_h_by) do
|
97
|
+
|
98
|
+
context "Duplicate keys" do
|
99
|
+
it "raises NRSER::ConflictError" do
|
100
|
+
expect {
|
101
|
+
NRSER.to_h_by([1, 2, 3]) { |i| i % 2 }
|
102
|
+
}.to raise_error NRSER::ConflictError
|
103
|
+
end
|
104
|
+
end # Duplicate keys
|
105
|
+
|
106
|
+
|
107
|
+
end # NRSER.to_h_by
|
108
|
+
|
109
|
+
|
96
110
|
end # NRSER Enumerable Methods
|
97
111
|
|
data/spec/nrser/types_spec.rb
CHANGED
@@ -149,6 +149,28 @@ describe NRSER::Types do
|
|
149
149
|
fail: [ [] ],
|
150
150
|
},
|
151
151
|
|
152
|
+
t.path => {
|
153
|
+
pass: [
|
154
|
+
'.',
|
155
|
+
Pathname.getwd,
|
156
|
+
],
|
157
|
+
|
158
|
+
fail: [
|
159
|
+
'',
|
160
|
+
123,
|
161
|
+
],
|
162
|
+
|
163
|
+
from_s: {
|
164
|
+
pass: [
|
165
|
+
'.',
|
166
|
+
],
|
167
|
+
|
168
|
+
fail: [
|
169
|
+
'',
|
170
|
+
],
|
171
|
+
},
|
172
|
+
}, # t.path
|
173
|
+
|
152
174
|
}.each do |type, tests|
|
153
175
|
if tests[:pass]
|
154
176
|
tests[:pass].each do |value|
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: nrser
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.24
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- nrser
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2017-09-
|
11
|
+
date: 2017-09-24 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -174,6 +174,7 @@ files:
|
|
174
174
|
- lib/nrser/types/is_a.rb
|
175
175
|
- lib/nrser/types/maybe.rb
|
176
176
|
- lib/nrser/types/numbers.rb
|
177
|
+
- lib/nrser/types/paths.rb
|
177
178
|
- lib/nrser/types/responds.rb
|
178
179
|
- lib/nrser/types/strings.rb
|
179
180
|
- lib/nrser/types/symbol.rb
|