nrser 0.0.20 → 0.0.21
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +3 -6
- data/lib/nrser/collection.rb +58 -20
- data/lib/nrser/enumerable.rb +155 -25
- data/lib/nrser/errors.rb +9 -0
- data/lib/nrser/hash.rb +1 -17
- data/lib/nrser/meta/class_attrs.rb +59 -9
- data/lib/nrser/open_struct.rb +60 -0
- data/lib/nrser/refinements/array.rb +4 -5
- data/lib/nrser/refinements/enumerable.rb +41 -0
- data/lib/nrser/refinements/enumerator.rb +7 -0
- data/lib/nrser/refinements/exception.rb +28 -0
- data/lib/nrser/refinements/hash.rb +9 -7
- data/lib/nrser/refinements/open_struct.rb +30 -0
- data/lib/nrser/refinements/set.rb +9 -0
- data/lib/nrser/refinements/string.rb +9 -0
- data/lib/nrser/refinements.rb +3 -0
- data/lib/nrser/types/attrs.rb +62 -35
- data/lib/nrser/types/bounded.rb +21 -4
- data/lib/nrser/types/combinators.rb +8 -4
- data/lib/nrser/types/is.rb +1 -1
- data/lib/nrser/types/responds.rb +110 -0
- data/lib/nrser/types/strings.rb +6 -0
- data/lib/nrser/types/type.rb +11 -6
- data/lib/nrser/types.rb +41 -6
- data/lib/nrser/version.rb +50 -1
- data/lib/nrser.rb +1 -0
- data/spec/nrser/enumerable_spec.rb +97 -0
- data/spec/nrser/hash_spec.rb +46 -2
- data/spec/nrser/open_struct_spec.rb +94 -0
- data/spec/nrser/refinements/array_spec.rb +25 -1
- data/spec/nrser/refinements/hash_spec.rb +30 -0
- data/spec/nrser/refinements/set_spec.rb +41 -0
- data/spec/nrser/types_spec.rb +13 -3
- metadata +58 -3
@@ -1,3 +1,5 @@
|
|
1
|
+
require 'pathname'
|
2
|
+
|
1
3
|
module NRSER
|
2
4
|
refine String do
|
3
5
|
def squish
|
@@ -27,5 +29,12 @@ module NRSER
|
|
27
29
|
|
28
30
|
alias_method :to_const, :constantize
|
29
31
|
|
32
|
+
# @return [Pathname]
|
33
|
+
# Convert self into a {Pathname}
|
34
|
+
#
|
35
|
+
def to_pn
|
36
|
+
Pathname.new self
|
37
|
+
end
|
38
|
+
|
30
39
|
end # refine String
|
31
40
|
end # NRSER
|
data/lib/nrser/refinements.rb
CHANGED
@@ -5,3 +5,6 @@ require_relative './refinements/hash'
|
|
5
5
|
require_relative './refinements/pathname'
|
6
6
|
require_relative './refinements/exception'
|
7
7
|
require_relative './refinements/binding'
|
8
|
+
require_relative './refinements/set'
|
9
|
+
require_relative './refinements/open_struct'
|
10
|
+
require_relative './refinements/enumerator'
|
data/lib/nrser/types/attrs.rb
CHANGED
@@ -8,62 +8,89 @@ module NRSER::Types
|
|
8
8
|
class Attrs < NRSER::Types::Type
|
9
9
|
def initialize attrs, **options
|
10
10
|
super **options
|
11
|
-
@attrs = attrs
|
11
|
+
@attrs = NRSER.map_values(attrs) { |name, type|
|
12
|
+
NRSER::Types.make type
|
13
|
+
}
|
12
14
|
end
|
13
15
|
|
14
16
|
def default_name
|
15
|
-
attrs_str = @attrs.map {|name, type|
|
17
|
+
attrs_str = @attrs.map { |name, type|
|
16
18
|
"#{ name }=#{ type.name }"
|
17
19
|
}.join(', ')
|
18
20
|
|
19
|
-
"#{ self.class.short_name }
|
21
|
+
"#{ self.class.short_name } #{ attrs_str }"
|
20
22
|
end
|
21
23
|
|
22
24
|
def test value
|
23
|
-
@attrs.all? {|name, type|
|
25
|
+
@attrs.all? { |name, type|
|
24
26
|
value.respond_to?(name) && type.test(value.method(name).call)
|
25
27
|
}
|
26
28
|
end
|
27
29
|
end # Attrs
|
28
30
|
|
29
|
-
def self.attrs attrs, options = {}
|
30
|
-
Attrs.new attrs, **options
|
31
|
-
end
|
32
31
|
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
32
|
+
# Eigenclass (Singleton Class)
|
33
|
+
# ========================================================================
|
34
|
+
#
|
35
|
+
class << self
|
36
|
+
def attrs attrs, options = {}
|
37
|
+
Attrs.new attrs, **options
|
38
|
+
end
|
39
|
+
|
40
|
+
def length *args
|
41
|
+
bounds = {}
|
42
|
+
options = {}
|
43
|
+
|
44
|
+
case args.length
|
45
|
+
when 1
|
46
|
+
case args[0]
|
47
|
+
when ::Integer
|
48
|
+
bounds[:min] = bounds[:max] = non_neg_int.check(args[0])
|
49
|
+
|
50
|
+
when ::Hash
|
51
|
+
options = NRSER.symbolize_keys args[0]
|
52
|
+
|
53
|
+
bounds[:min] = options.delete :min
|
54
|
+
bounds[:max] = options.delete :max
|
55
|
+
|
56
|
+
if length = options.delete(:length)
|
57
|
+
bounds[:min] = length
|
58
|
+
bounds[:max] = length
|
47
59
|
end
|
48
|
-
|
60
|
+
|
61
|
+
else
|
62
|
+
raise ArgumentError, <<-END.squish
|
63
|
+
arg must be positive integer or option hash, found:
|
64
|
+
#{ args[0].inspect } of type #{ args[0].class }
|
65
|
+
END
|
66
|
+
end
|
49
67
|
|
50
|
-
|
68
|
+
when 2
|
69
|
+
bounds[:min] = bounds[:max] = non_neg_int.check(args[0])
|
70
|
+
options = args[1]
|
71
|
+
|
72
|
+
else
|
51
73
|
raise ArgumentError, <<-END.squish
|
52
|
-
|
53
|
-
#{ args[0].inspect } of type #{ args[0].class }
|
74
|
+
must provided 1 or 2 args.
|
54
75
|
END
|
55
76
|
end
|
56
77
|
|
57
|
-
|
58
|
-
bounds[:min] = bounds[:max] = non_neg_int.check(args[0])
|
59
|
-
options = args[1]
|
78
|
+
bounded_type = bounded bounds
|
60
79
|
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
80
|
+
length_type = if !bounded_type.min.nil? && bounded_type.min >= 0
|
81
|
+
# We don't need the non-neg check
|
82
|
+
bounded_type
|
83
|
+
else
|
84
|
+
# We do need the non-neg check
|
85
|
+
intersection(non_neg_int, bounded_type)
|
86
|
+
end
|
87
|
+
|
88
|
+
options[:name] ||= "Length<#{ bounded_type.name }>"
|
89
|
+
|
90
|
+
attrs({ length: length_type }, options)
|
91
|
+
end # #length
|
92
|
+
|
66
93
|
|
67
|
-
|
68
|
-
|
94
|
+
end # class << self (Eigenclass)
|
95
|
+
|
69
96
|
end # NRSER::Types
|
data/lib/nrser/types/bounded.rb
CHANGED
@@ -5,9 +5,26 @@ using NRSER
|
|
5
5
|
|
6
6
|
module NRSER::Types
|
7
7
|
class Bounded < NRSER::Types::Type
|
8
|
-
|
9
|
-
|
10
|
-
|
8
|
+
|
9
|
+
# @!attribute [r] min
|
10
|
+
# @return [Number]
|
11
|
+
# Minimum value.
|
12
|
+
attr_reader :min
|
13
|
+
|
14
|
+
|
15
|
+
# @!attribute [r] max
|
16
|
+
# @return [Number]
|
17
|
+
# Minimum value.
|
18
|
+
attr_reader :max
|
19
|
+
|
20
|
+
|
21
|
+
def initialize min: nil,
|
22
|
+
max: nil,
|
23
|
+
**options
|
24
|
+
super **options
|
25
|
+
|
26
|
+
@min = min
|
27
|
+
@max = max
|
11
28
|
end
|
12
29
|
|
13
30
|
def test value
|
@@ -25,7 +42,7 @@ module NRSER::Types
|
|
25
42
|
"#{ name }=#{ value }"
|
26
43
|
}.join(', ')
|
27
44
|
|
28
|
-
"#{ self.class.short_name }
|
45
|
+
"#{ self.class.short_name } #{ attrs_str }"
|
29
46
|
end
|
30
47
|
end # Bounded
|
31
48
|
|
@@ -13,11 +13,11 @@ module NRSER::Types
|
|
13
13
|
@types = types.map {|type| NRSER::Types.make type}
|
14
14
|
end
|
15
15
|
|
16
|
-
def
|
16
|
+
def default_name
|
17
17
|
@name || (
|
18
|
-
"#{ self.class.short_name }
|
18
|
+
"#{ self.class.short_name }<" +
|
19
19
|
@types.map {|type| type.name }.join(',') +
|
20
|
-
"
|
20
|
+
">"
|
21
21
|
)
|
22
22
|
end
|
23
23
|
|
@@ -42,7 +42,7 @@ module NRSER::Types
|
|
42
42
|
}
|
43
43
|
|
44
44
|
raise TypeError,
|
45
|
-
"none of
|
45
|
+
"none of combinator #{ self.to_s } types could convert #{ s.inspect }"
|
46
46
|
end
|
47
47
|
|
48
48
|
def == other
|
@@ -69,6 +69,10 @@ module NRSER::Types
|
|
69
69
|
def test value
|
70
70
|
@types.all? {|type| type.test value}
|
71
71
|
end
|
72
|
+
|
73
|
+
def default_name
|
74
|
+
"( #{ @types.map { |t| t.name }.join ' | ' } )"
|
75
|
+
end
|
72
76
|
end
|
73
77
|
|
74
78
|
# match all of the types
|
data/lib/nrser/types/is.rb
CHANGED
@@ -0,0 +1,110 @@
|
|
1
|
+
|
2
|
+
# @todo document NRSER::Types module.
|
3
|
+
module NRSER::Types
|
4
|
+
|
5
|
+
# @todo document Responds class.
|
6
|
+
class Responds < NRSER::Types::Type
|
7
|
+
|
8
|
+
# Constants
|
9
|
+
# ======================================================================
|
10
|
+
|
11
|
+
|
12
|
+
# Class Methods
|
13
|
+
# ======================================================================
|
14
|
+
|
15
|
+
|
16
|
+
# Attributes
|
17
|
+
# ======================================================================
|
18
|
+
|
19
|
+
|
20
|
+
# Constructor
|
21
|
+
# ======================================================================
|
22
|
+
|
23
|
+
# Instantiate a new `Responds`.
|
24
|
+
def initialize map,
|
25
|
+
public: true,
|
26
|
+
**options
|
27
|
+
@map = NRSER.map_values(map) { |args, type|
|
28
|
+
NRSER::Types.make type
|
29
|
+
}
|
30
|
+
end # #initialize
|
31
|
+
|
32
|
+
|
33
|
+
# Instance Methods
|
34
|
+
# ======================================================================
|
35
|
+
|
36
|
+
|
37
|
+
def default_name
|
38
|
+
attrs_str = @map.map { |args, type|
|
39
|
+
args_str = args[1..-1].map(&:inspect).join ', '
|
40
|
+
"#{ args[0] }(#{ args_str })=#{ type.name }"
|
41
|
+
}.join(', ')
|
42
|
+
|
43
|
+
"#{ self.class.short_name } #{ attrs_str }"
|
44
|
+
end
|
45
|
+
|
46
|
+
|
47
|
+
# @todo Document test method.
|
48
|
+
#
|
49
|
+
# @param [type] arg_name
|
50
|
+
# @todo Add name param description.
|
51
|
+
#
|
52
|
+
# @return [return_type]
|
53
|
+
# @todo Document return value.
|
54
|
+
#
|
55
|
+
def test value
|
56
|
+
@map.all? { |args, type|
|
57
|
+
response = if @public
|
58
|
+
value.public_send *args
|
59
|
+
else
|
60
|
+
value.send *args
|
61
|
+
end
|
62
|
+
|
63
|
+
type.test response
|
64
|
+
}
|
65
|
+
end # #test
|
66
|
+
|
67
|
+
|
68
|
+
end # class Responds
|
69
|
+
|
70
|
+
|
71
|
+
# Eigenclass (Singleton Class)
|
72
|
+
# ========================================================================
|
73
|
+
#
|
74
|
+
class << self
|
75
|
+
|
76
|
+
|
77
|
+
# @todo Document responds method.
|
78
|
+
#
|
79
|
+
# @param [type] arg_name
|
80
|
+
# @todo Add name param description.
|
81
|
+
#
|
82
|
+
# @return [return_type]
|
83
|
+
# @todo Document return value.
|
84
|
+
#
|
85
|
+
def responds *args
|
86
|
+
Responds.new *args
|
87
|
+
end # #responds
|
88
|
+
|
89
|
+
|
90
|
+
|
91
|
+
# @todo Document respond_to Responds.
|
92
|
+
#
|
93
|
+
# @param [type] arg_name
|
94
|
+
# @todo Add name param description.
|
95
|
+
#
|
96
|
+
# @return [return_type]
|
97
|
+
# @todo Document return value.
|
98
|
+
#
|
99
|
+
def respond_to name, **options
|
100
|
+
responds(
|
101
|
+
{[:respond_to?, name] => NRSER::Types::TRUE},
|
102
|
+
**options
|
103
|
+
)
|
104
|
+
end # #respond_to
|
105
|
+
|
106
|
+
|
107
|
+
end # class << self (Eigenclass)
|
108
|
+
|
109
|
+
|
110
|
+
end # module NRSER::Types
|
data/lib/nrser/types/strings.rb
CHANGED
data/lib/nrser/types/type.rb
CHANGED
@@ -24,14 +24,19 @@ module NRSER::Types
|
|
24
24
|
raise NotImplementedError
|
25
25
|
end
|
26
26
|
|
27
|
-
def check value
|
28
|
-
|
29
|
-
|
30
|
-
|
27
|
+
def check value, &make_fail_message
|
28
|
+
# success case
|
29
|
+
return value if test value
|
30
|
+
|
31
|
+
msg = if make_fail_message
|
32
|
+
make_fail_message.call type: self, value: value
|
33
|
+
else
|
34
|
+
NRSER.squish <<-END
|
35
|
+
value #{ value.inspect } failed check #{ self.to_s }
|
31
36
|
END
|
32
37
|
end
|
33
38
|
|
34
|
-
|
39
|
+
raise TypeError.new msg
|
35
40
|
end
|
36
41
|
|
37
42
|
def respond_to? name, include_all = false
|
@@ -55,7 +60,7 @@ module NRSER::Types
|
|
55
60
|
end
|
56
61
|
|
57
62
|
def to_s
|
58
|
-
"
|
63
|
+
"`Type: #{ name }`"
|
59
64
|
end
|
60
65
|
end # Type
|
61
66
|
end # NRSER::Types
|
data/lib/nrser/types.rb
CHANGED
@@ -8,6 +8,7 @@ require 'nrser/types/where'
|
|
8
8
|
require 'nrser/types/combinators'
|
9
9
|
require 'nrser/types/maybe'
|
10
10
|
require 'nrser/types/attrs'
|
11
|
+
require 'nrser/types/responds'
|
11
12
|
|
12
13
|
using NRSER
|
13
14
|
|
@@ -32,21 +33,55 @@ module NRSER::Types
|
|
32
33
|
make(type).test value
|
33
34
|
end
|
34
35
|
|
35
|
-
def self.match value,
|
36
|
-
|
36
|
+
def self.match value, *clauses
|
37
|
+
if clauses.empty?
|
38
|
+
raise ArgumentError.new NRSER.dedent <<-END
|
39
|
+
Must supply either a single {type => expression} hash argument or a
|
40
|
+
even amount of arguments representing (type, expression) pairs after
|
41
|
+
`value`.
|
42
|
+
|
43
|
+
#{ NRSER::Version.doc_url 'NRSER/Types#match-class_method' }
|
44
|
+
END
|
45
|
+
end
|
46
|
+
|
47
|
+
enum = if clauses.length == 1 && clauses.first.respond_to?(:each_pair)
|
48
|
+
clauses.first.each_pair
|
49
|
+
else
|
50
|
+
unless clauses.length % 2 == 0
|
51
|
+
raise TypeError.new NRSER.dedent <<-END
|
52
|
+
When passing a list of clauses, it must be an even length
|
53
|
+
representing (type, expression) pairs.
|
54
|
+
|
55
|
+
Found an argument list with length #{ clauses.length }:
|
56
|
+
|
57
|
+
#{ clauses }
|
58
|
+
END
|
59
|
+
end
|
60
|
+
|
61
|
+
clauses.each_slice(2)
|
62
|
+
end
|
63
|
+
|
64
|
+
enum.each { |type, expression|
|
37
65
|
if test value, type
|
38
|
-
|
66
|
+
# OK, we matched! Is the corresponding expression callable?
|
67
|
+
if expression.respond_to? :call
|
68
|
+
# It is; invoke and return result.
|
69
|
+
return expression.call value
|
70
|
+
else
|
71
|
+
# It's not; assume it's a value and return it.
|
72
|
+
return expression
|
73
|
+
end
|
39
74
|
end
|
40
75
|
}
|
41
76
|
|
42
77
|
raise TypeError, <<-END.dedent
|
43
|
-
|
78
|
+
Could not match value
|
44
79
|
|
45
|
-
|
80
|
+
#{ value.inspect }
|
46
81
|
|
47
82
|
to any of types
|
48
83
|
|
49
|
-
#{
|
84
|
+
#{ enum.map {|type, expression| "\n #{ type.inspect }"} }
|
50
85
|
|
51
86
|
END
|
52
87
|
end
|
data/lib/nrser/version.rb
CHANGED
@@ -1,3 +1,52 @@
|
|
1
1
|
module NRSER
|
2
|
-
VERSION = "0.0.
|
2
|
+
VERSION = "0.0.21"
|
3
|
+
|
4
|
+
module Version
|
5
|
+
|
6
|
+
# @return [Gem::Version]
|
7
|
+
# Parse of {NRSER::VERSION}.
|
8
|
+
#
|
9
|
+
def self.gem_version
|
10
|
+
Gem::Version.new VERSION
|
11
|
+
end # .gem_version
|
12
|
+
|
13
|
+
|
14
|
+
# The `Gem::Version` "release" for {NRSER::VERSION} - everything before
|
15
|
+
# any `-<alpha-numeric>` prerelease part (like `-dev`).
|
16
|
+
#
|
17
|
+
# @see https://ruby-doc.org/stdlib-2.4.1/libdoc/rubygems/rdoc/Gem/Version.html#method-i-release
|
18
|
+
#
|
19
|
+
# @example
|
20
|
+
#
|
21
|
+
# NRSER::VERSION
|
22
|
+
# # => '0.0.21.dev'
|
23
|
+
#
|
24
|
+
# NRSER::Version.release
|
25
|
+
# # => #<Gem::Version "0.0.21">
|
26
|
+
#
|
27
|
+
# @return [Gem::Version]
|
28
|
+
#
|
29
|
+
def self.release
|
30
|
+
gem_version.release
|
31
|
+
end # .release
|
32
|
+
|
33
|
+
|
34
|
+
# Get a URL to a place in the current version's docs on ruby-docs.org.
|
35
|
+
#
|
36
|
+
# @param [String] rel_path
|
37
|
+
# Relative path.
|
38
|
+
#
|
39
|
+
# @return [String]
|
40
|
+
# The RubyDocs URL.
|
41
|
+
#
|
42
|
+
def self.doc_url rel_path
|
43
|
+
File.join(
|
44
|
+
"http://www.rubydoc.info/gems/nrser",
|
45
|
+
NRSER::Version.release.to_s,
|
46
|
+
rel_path
|
47
|
+
)
|
48
|
+
end # .doc_url
|
49
|
+
|
50
|
+
|
51
|
+
end
|
3
52
|
end
|
data/lib/nrser.rb
CHANGED
@@ -0,0 +1,97 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe "NRSER Enumerable Methods" do
|
4
|
+
|
5
|
+
describe NRSER.method(:find_bounded) do
|
6
|
+
|
7
|
+
context "when just :length bounds arg is provided" do
|
8
|
+
it "returns found elements when length is correct" do
|
9
|
+
expect(
|
10
|
+
subject.([1, 2, 3], length: 1) { |i| i == 2 }
|
11
|
+
).to eq [2]
|
12
|
+
end
|
13
|
+
|
14
|
+
it "raises TypeError when length in incorrect" do
|
15
|
+
expect {
|
16
|
+
subject.([1, 2, 3], length: 2) { |i| i == 2 }
|
17
|
+
}.to raise_error TypeError
|
18
|
+
end
|
19
|
+
end # when just :length bounds arg is provided
|
20
|
+
|
21
|
+
context "when just :min bounds arg is provided" do
|
22
|
+
it "returns found elements when min is correct" do
|
23
|
+
expect(
|
24
|
+
subject.([1, 2, 3], min: 1) { |i| i == 2 }
|
25
|
+
).to eq [2]
|
26
|
+
end
|
27
|
+
|
28
|
+
it "raises TypeError when min in incorrect" do
|
29
|
+
expect {
|
30
|
+
subject.([1, 2, 3], min: 2) { |i| i == 2 }
|
31
|
+
}.to raise_error TypeError
|
32
|
+
end
|
33
|
+
end # when just :min bounds arg is provided
|
34
|
+
|
35
|
+
context "when just :max bounds arg is provided" do
|
36
|
+
it "returns found elements when max is correct" do
|
37
|
+
expect(
|
38
|
+
subject.([1, 2, 3], max: 2) { |i| i >= 2 }
|
39
|
+
).to eq [2, 3]
|
40
|
+
end
|
41
|
+
|
42
|
+
it "raises TypeError when max in incorrect" do
|
43
|
+
expect {
|
44
|
+
subject.([1, 2, 3], max: 1) { |i| i >= 2 }
|
45
|
+
}.to raise_error TypeError
|
46
|
+
end
|
47
|
+
end # when just :max bounds arg is provided
|
48
|
+
|
49
|
+
|
50
|
+
context "when :min and :max bounds args are both provided" do
|
51
|
+
it "returns found elements when min and max are correct" do
|
52
|
+
expect(
|
53
|
+
subject.([1, 2, 3], min: 1, max: 2) { |i| i >= 2 }
|
54
|
+
).to eq [2, 3]
|
55
|
+
end
|
56
|
+
|
57
|
+
it "raises TypeError when min is incorrect" do
|
58
|
+
expect {
|
59
|
+
subject.([1, 2, 3], min: 1, max: 2) { |i| false }
|
60
|
+
}.to raise_error TypeError
|
61
|
+
end
|
62
|
+
|
63
|
+
it "raises TypeError when max is incorrect" do
|
64
|
+
expect {
|
65
|
+
subject.([1, 2, 3], min: 1, max: 2) { |i| true }
|
66
|
+
}.to raise_error TypeError
|
67
|
+
end
|
68
|
+
end # when :min and :max bounds args are both provided
|
69
|
+
|
70
|
+
end # NRSER.method(:find_bounded)
|
71
|
+
|
72
|
+
|
73
|
+
describe NRSER.method(:find_only) do
|
74
|
+
|
75
|
+
it "returns the element when only one is found" do
|
76
|
+
expect(
|
77
|
+
subject.call [1, 2, 3] { |i| i == 2 }
|
78
|
+
).to be 2
|
79
|
+
end
|
80
|
+
|
81
|
+
it "raises TypeError when more than one element is found" do
|
82
|
+
expect {
|
83
|
+
subject.call [1, 2, 3] { |i| i >= 2 }
|
84
|
+
}.to raise_error TypeError
|
85
|
+
end
|
86
|
+
|
87
|
+
it "raises TypeError when no elements are found" do
|
88
|
+
expect {
|
89
|
+
subject.call [1, 2, 3] { |i| false }
|
90
|
+
}.to raise_error TypeError
|
91
|
+
end
|
92
|
+
|
93
|
+
end # NRSER.method(:find_only)
|
94
|
+
|
95
|
+
|
96
|
+
end # NRSER Enumerable Methods
|
97
|
+
|
data/spec/nrser/hash_spec.rb
CHANGED
@@ -1,8 +1,11 @@
|
|
1
|
+
require 'set'
|
2
|
+
require 'ostruct'
|
3
|
+
|
1
4
|
require 'spec_helper'
|
2
5
|
|
3
6
|
using NRSER
|
4
7
|
|
5
|
-
describe NRSER.method(:
|
8
|
+
describe NRSER.method(:leaves) do
|
6
9
|
it do
|
7
10
|
expect(NRSER.leaves({a: 1, b: 2})).to eq ({[:a] => 1, [:b] => 2})
|
8
11
|
expect(
|
@@ -21,4 +24,45 @@ describe NRSER.method(:truncate) do
|
|
21
24
|
[:b] => 'bee',
|
22
25
|
})
|
23
26
|
end
|
24
|
-
end #
|
27
|
+
end # NRSER.leaves
|
28
|
+
|
29
|
+
describe NRSER.method(:map_values) do
|
30
|
+
|
31
|
+
it "handles hashes" do
|
32
|
+
expect(
|
33
|
+
NRSER.map_values({a: 1, b: 2}) { |k, v| v * 3 }
|
34
|
+
).to eq(
|
35
|
+
{a: 3, b: 6}
|
36
|
+
)
|
37
|
+
end # handles hashes
|
38
|
+
|
39
|
+
|
40
|
+
it "handles arrays" do
|
41
|
+
expect(
|
42
|
+
NRSER.map_values([:a, :b, :c]) { |k, v| "#{ k } is ok!" }
|
43
|
+
).to eq(
|
44
|
+
{a: "a is ok!", b: "b is ok!", c: "c is ok!"}
|
45
|
+
)
|
46
|
+
end # handles arrays
|
47
|
+
|
48
|
+
|
49
|
+
it "handles sets" do
|
50
|
+
expect(
|
51
|
+
NRSER.map_values(Set.new [:a, :b, :c]) { |k, v| "#{ k } is ok!" }
|
52
|
+
).to eq(
|
53
|
+
{a: "a is ok!", b: "b is ok!", c: "c is ok!"}
|
54
|
+
)
|
55
|
+
end # handles sets
|
56
|
+
|
57
|
+
|
58
|
+
it "handles OpenStruct instances" do
|
59
|
+
expect(
|
60
|
+
NRSER.map_values(OpenStruct.new a: 1, b: 2) { |k, v| v * 3 }
|
61
|
+
).to eq(
|
62
|
+
{a: 3, b: 6}
|
63
|
+
)
|
64
|
+
end # handles OpenStruct instances
|
65
|
+
|
66
|
+
|
67
|
+
end # NRSER.map_values
|
68
|
+
|