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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: bce188e694cb5fd687f3085a43602dc303a1c1ab
4
- data.tar.gz: affc25e12e51d899523c3a5fe5db6c498a997d8b
3
+ metadata.gz: ad84454dbdd85a4a86dbb940a0901cafe0effaef
4
+ data.tar.gz: 9992915527ce7f7749aac2d9bdf319a05507fd23
5
5
  SHA512:
6
- metadata.gz: 1946f2af31a5f40a84533d114d02513729308eb7ba06d3a2fd2f57ed1d4326718432a9aff3e64bb8be1e38703ffe1663bacc0ba0beeb67b68018472b2c8ab941
7
- data.tar.gz: '08ac5aff6d524538547eef3b00e07aa916301b83bb6812980af20d341c714a25dfcd0d1a8957cf939fd112becdac7b3182507c20c97913d56b08888d7639d60e'
6
+ metadata.gz: 995db23a4d353e6a54fec4480e3d17175b99efb75a0a08cc0583a3b166fa1153a26ce58b66d2b592306a17d495ca3544a805a06a03fb06516337f072ee22eb91
7
+ data.tar.gz: 47488b4ca3a7655f5264578a6e9283b04e2e1148093c72ec032cbc03720f098d6e7531cd44ccc1e20f9ec3e4ea063a905fb4f4699b6793042a816e0a7f5d6ca7
@@ -115,7 +115,7 @@ module NRSER
115
115
  key = block.call element
116
116
 
117
117
  if result.key? key
118
- raise NRSER::ConflictError.dedented <<-END
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
@@ -21,7 +21,7 @@ module NRSER::Types
21
21
  end # IsA
22
22
 
23
23
  # class membership
24
- def self.is_a klass
25
- IsA.new klass
24
+ def self.is_a klass, **options
25
+ IsA.new klass, **options
26
26
  end
27
27
  end # NRSER::Types
@@ -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
+
@@ -7,10 +7,29 @@ module NRSER::Types
7
7
  name.split('::').last
8
8
  end
9
9
 
10
- def initialize **options
11
- @name = options[:name]
12
- @from_s = options[:from_s]
13
- end
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
- require 'nrser/refinements'
4
- require 'nrser/types/type'
5
- require 'nrser/types/is'
6
- require 'nrser/types/is_a'
7
- require 'nrser/types/where'
8
- require 'nrser/types/combinators'
9
- require 'nrser/types/maybe'
10
- require 'nrser/types/attrs'
11
- require 'nrser/types/responds'
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
- # make a type.
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
- # things that define values, which may need to call the functions defined
105
- # above
106
- require 'nrser/types/any'
107
- require 'nrser/types/booleans'
108
- require 'nrser/types/numbers'
109
- require 'nrser/types/strings'
110
- require 'nrser/types/symbol'
111
- require 'nrser/types/array'
112
- require 'nrser/types/hash'
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
@@ -1,5 +1,5 @@
1
1
  module NRSER
2
- VERSION = "0.0.23"
2
+ VERSION = "0.0.24"
3
3
 
4
4
  module Version
5
5
 
@@ -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
 
@@ -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.23
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-17 00:00:00.000000000 Z
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