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