nrser 0.0.25 → 0.0.26

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.
Files changed (77) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +39 -11
  3. data/lib/nrser.rb +5 -1
  4. data/lib/nrser/array.rb +10 -53
  5. data/lib/nrser/enumerable.rb +21 -0
  6. data/lib/nrser/hash.rb +13 -476
  7. data/lib/nrser/hash/bury.rb +154 -0
  8. data/lib/nrser/hash/deep_merge.rb +57 -0
  9. data/lib/nrser/hash/except_keys.rb +42 -0
  10. data/lib/nrser/hash/guess_label_key_type.rb +37 -0
  11. data/lib/nrser/hash/slice_keys.rb +41 -0
  12. data/lib/nrser/hash/stringify_keys.rb +37 -0
  13. data/lib/nrser/hash/symbolize_keys.rb +41 -0
  14. data/lib/nrser/hash/transform_keys.rb +45 -0
  15. data/lib/nrser/merge_by.rb +26 -0
  16. data/lib/nrser/message.rb +125 -0
  17. data/lib/nrser/meta/props.rb +2 -2
  18. data/lib/nrser/meta/props/prop.rb +5 -2
  19. data/lib/nrser/object.rb +5 -0
  20. data/lib/nrser/object/as_array.rb +37 -0
  21. data/lib/nrser/object/as_hash.rb +101 -0
  22. data/lib/nrser/{truthy.rb → object/truthy.rb} +0 -0
  23. data/lib/nrser/proc.rb +132 -0
  24. data/lib/nrser/refinements.rb +1 -2
  25. data/lib/nrser/refinements/array.rb +94 -5
  26. data/lib/nrser/refinements/enumerable.rb +5 -0
  27. data/lib/nrser/refinements/hash.rb +43 -6
  28. data/lib/nrser/refinements/object.rb +22 -2
  29. data/lib/nrser/refinements/symbol.rb +12 -0
  30. data/lib/nrser/refinements/tree.rb +41 -0
  31. data/lib/nrser/rspex.rb +329 -0
  32. data/lib/nrser/string.rb +3 -0
  33. data/lib/nrser/string/looks_like.rb +51 -0
  34. data/lib/nrser/temp/where.rb +52 -0
  35. data/lib/nrser/tree.rb +86 -0
  36. data/lib/nrser/tree/leaves.rb +92 -0
  37. data/lib/nrser/tree/map_leaves.rb +63 -0
  38. data/lib/nrser/tree/transform.rb +30 -0
  39. data/lib/nrser/types.rb +9 -4
  40. data/lib/nrser/types/any.rb +1 -1
  41. data/lib/nrser/types/array.rb +167 -25
  42. data/lib/nrser/types/{hash.rb → hashes.rb} +19 -5
  43. data/lib/nrser/types/in.rb +47 -0
  44. data/lib/nrser/types/is_a.rb +2 -2
  45. data/lib/nrser/types/labels.rb +49 -0
  46. data/lib/nrser/types/numbers.rb +63 -27
  47. data/lib/nrser/types/pairs.rb +109 -0
  48. data/lib/nrser/types/responds.rb +2 -3
  49. data/lib/nrser/types/strings.rb +17 -18
  50. data/lib/nrser/types/symbols.rb +39 -0
  51. data/lib/nrser/types/trees.rb +93 -0
  52. data/lib/nrser/types/tuples.rb +116 -0
  53. data/lib/nrser/types/type.rb +26 -2
  54. data/lib/nrser/version.rb +1 -1
  55. data/spec/nrser/hash/{guess_name_type_spec.rb → guess_label_key_type_spec.rb} +3 -3
  56. data/spec/nrser/hash_spec.rb +0 -20
  57. data/spec/nrser/merge_by_spec.rb +73 -0
  58. data/spec/nrser/meta/props_spec.rb +136 -43
  59. data/spec/nrser/op/message_spec.rb +62 -0
  60. data/spec/nrser/refinements/array_spec.rb +36 -0
  61. data/spec/nrser/refinements/hash_spec.rb +34 -0
  62. data/spec/nrser/string/looks_like_spec.rb +31 -0
  63. data/spec/nrser/tree/each_branch_spec.rb +82 -0
  64. data/spec/nrser/tree/leaves_spec.rb +112 -0
  65. data/spec/nrser/tree/transform_spec.rb +165 -0
  66. data/spec/nrser/types/array_spec.rb +82 -0
  67. data/spec/nrser/types/attrs_spec.rb +4 -4
  68. data/spec/nrser/types/pairs_spec.rb +41 -0
  69. data/spec/nrser/types/paths_spec.rb +3 -3
  70. data/spec/nrser/types/strings_spec.rb +66 -0
  71. data/spec/nrser/types/symbols_spec.rb +38 -0
  72. data/spec/nrser/types/tuples_spec.rb +37 -0
  73. data/spec/nrser/types_spec.rb +0 -13
  74. data/spec/spec_helper.rb +71 -22
  75. metadata +58 -10
  76. data/lib/nrser/spex.rb +0 -68
  77. data/lib/nrser/types/symbol.rb +0 -23
@@ -0,0 +1,62 @@
1
+ require 'spec_helper'
2
+
3
+ require 'nrser/refinements'
4
+ using NRSER
5
+
6
+ require 'nrser/refinements/types'
7
+ using NRSER::Types
8
+
9
+
10
+ describe NRSER::Message, type: :class do
11
+
12
+ describe "#to_proc" do
13
+
14
+ describe_section "mapping an Enumerable using &message" do
15
+ subject { ->( message ) { enum.map &message } }
16
+
17
+ context_where enum: [ [], [1], [1, 2] ] do
18
+
19
+ describe_called_with NRSER::Message.new( :length ) do
20
+ it { is_expected.to eq [0, 1, 2] }
21
+ end # called with
22
+
23
+ describe_called_with NRSER::Message.new( :first ) do
24
+ it { is_expected.to eq [nil, 1, 1] }
25
+ end # called with :first
26
+
27
+ end # enum
28
+
29
+ end # mapping an Enumerable using &message
30
+
31
+ end # #to_proc
32
+
33
+
34
+ describe_section "Refinements" do
35
+ # ========================================================================
36
+
37
+ describe "Array#to_message" do
38
+
39
+ subject { array.to_message }
40
+
41
+ context_where array: [:fetch, :x] do
42
+ it {
43
+ is_expected.to be_a( NRSER::Message ).and have_attributes \
44
+ symbol: :fetch,
45
+ args: [:x],
46
+ block: nil
47
+ }
48
+
49
+ describe_sent_to x: 'ex', y: 'why?' do
50
+ it { is_expected.to eq 'ex' }
51
+ end # sent to x: 1, y: 2
52
+
53
+ end # array: [:fetch, :x]
54
+
55
+ end # Array#to_message
56
+
57
+
58
+ end # section Refinements
59
+ # ************************************************************************
60
+
61
+
62
+ end # NRSER::Message, type: :class
@@ -12,6 +12,7 @@ describe 'Refinement Array#map_values' do
12
12
  end
13
13
  end # Refinement Array#map_values
14
14
 
15
+
15
16
  describe 'Refinement Array#find_bounded' do
16
17
  it do
17
18
  expect(
@@ -24,6 +25,7 @@ describe 'Refinement Array#find_bounded' do
24
25
  end
25
26
  end # Refinement Array#map_values
26
27
 
28
+
27
29
  describe 'Refinement Array#find_only' do
28
30
  it do
29
31
  expect(
@@ -35,3 +37,37 @@ describe 'Refinement Array#find_only' do
35
37
  }.to raise_error TypeError
36
38
  end
37
39
  end # Refinement Array#map_values
40
+
41
+
42
+ describe "Refinement Array#leaves" do
43
+ subject { [:a, :b, :c].leaves }
44
+
45
+ it { is_expected.to eq( {[0] => :a, [1] => :b, [2] => :c}) }
46
+ end # Refinement Array#leaves
47
+
48
+
49
+ describe "Refinement Array#each_branch" do
50
+ let( :abc_array ) { [:a, :b, :c] }
51
+
52
+ context "called with no block" do
53
+ subject { abc_array.each_branch }
54
+
55
+ it {
56
+ is_expected.to be_a( Enumerator ).
57
+ and have_attributes size: 3
58
+ }
59
+ end # called with no block
60
+
61
+ context "called with a block" do
62
+ subject {
63
+ result = {}
64
+ abc_array.each_branch { |key, value|
65
+ result[key] = value
66
+ }
67
+ result
68
+ }
69
+
70
+ it { is_expected.to eq(0 => :a, 1 => :b, 2 => :c) }
71
+ end # called with a block
72
+
73
+ end # Refinement Array#each_branch
@@ -41,3 +41,37 @@ describe 'Refinement Hash#find_only' do
41
41
  }.to raise_error TypeError
42
42
  end
43
43
  end # Refinement Hash#map_values
44
+
45
+
46
+ describe "Refinement Hash#leaves" do
47
+ subject { {a: 1, b: 2, c: 3}.leaves }
48
+
49
+ it { is_expected.to eq( {[:a] => 1, [:b] => 2, [:c] => 3}) }
50
+ end # Refinement Hash#leaves
51
+
52
+
53
+ describe "Refinement Hash#each_branch" do
54
+ let( :abc_hash ) { {a: 1, b: 2, c: 3} }
55
+
56
+ context "called with no block" do
57
+ subject { abc_hash.each_branch }
58
+
59
+ it {
60
+ is_expected.to be_a( Enumerator ).
61
+ and have_attributes size: 3
62
+ }
63
+ end # called with no block
64
+
65
+ context "called with a block" do
66
+ subject {
67
+ result = {}
68
+ abc_hash.each_branch { |key, value|
69
+ result[key] = value * value
70
+ }
71
+ result
72
+ }
73
+
74
+ it { is_expected.to eq(a: 1, b: 4, c: 9) }
75
+ end # called with a block
76
+
77
+ end # Refinement Hash#each_branch
@@ -0,0 +1,31 @@
1
+ require 'spec_helper'
2
+
3
+
4
+ # NRSER.looks_like_json_array?
5
+ # ========================================================================
6
+ #
7
+ describe "NRSER.looks_like_json_array?" do
8
+ subject { NRSER.method :looks_like_json_array? }
9
+
10
+ multiline = <<-END
11
+
12
+ [
13
+ 1,
14
+ 2,
15
+ 3
16
+ ]
17
+
18
+ END
19
+
20
+ it_behaves_like "function",
21
+ mapping: {
22
+ '' => false,
23
+ '[]' => true,
24
+ '[1, 2, 3]' => true,
25
+ multiline => true,
26
+ }
27
+
28
+
29
+ end # NRSER.looks_like_json_array?
30
+
31
+ # ************************************************************************
@@ -0,0 +1,82 @@
1
+ require 'spec_helper'
2
+
3
+ require 'nrser/refinements'
4
+ using NRSER
5
+
6
+ describe "NRSER.each_branch" do
7
+
8
+ subject { NRSER.method :each_branch }
9
+
10
+ context "called without a block" do
11
+ context "called with arrays" do
12
+ when_called_with( [] ) {
13
+ it {
14
+ is_expected.to be_a( Enumerator ).
15
+ and have_attributes size: 0
16
+ }
17
+ }
18
+
19
+ when_called_with( [:x, :y, :z] ) {
20
+ it {
21
+ is_expected.to be_a( Enumerator ).
22
+ and have_attributes size: 3
23
+ }
24
+ }
25
+ end # called with arrays
26
+
27
+ context "called with hashes" do
28
+ when_called_with( {} ) {
29
+ it {
30
+ is_expected.to be_a( Enumerator ).
31
+ and have_attributes size: 0
32
+ }
33
+ }
34
+ end # called with hashes
35
+
36
+ context "convert returned Enumerator to array" do
37
+ subject {
38
+ # CRASHES VM!!!
39
+ # ->( *args ) { super().call( *args ).to_a }
40
+ ->( *args ) { NRSER.each_branch( *args ).to_a }
41
+ }
42
+
43
+ it_behaves_like 'function',
44
+ mapping: {
45
+ [ {x: 'ex', y: 'why?', z: 'zee!'} ] => [
46
+ [:x, 'ex'],
47
+ [:y, 'why?'],
48
+ [:z, 'zee!'],
49
+ ],
50
+
51
+ [ [:x, :y, :z] ] => [
52
+ [0, :x],
53
+ [1, :y],
54
+ [2, :z],
55
+ ]
56
+ }
57
+ end # convert Enumerator to array
58
+ end # called without a block
59
+
60
+ context "called with a block" do
61
+
62
+ context "called with arrays" do
63
+
64
+ subject {
65
+ input = [:x, :y, :z]
66
+ result = {}
67
+ super().call( input ) { |index, value|
68
+ result[index] = value
69
+ }
70
+ result
71
+ }
72
+
73
+ it {
74
+ is_expected.to eq(0 => :x, 1 => :y, 2 => :z)
75
+ }
76
+
77
+ end # called with arrays
78
+
79
+ end # called with a block
80
+
81
+ end # NRSER.each_branch
82
+
@@ -0,0 +1,112 @@
1
+ require 'spec_helper'
2
+
3
+ describe "NRSER.leaves" do
4
+ subject { NRSER.method :leaves }
5
+
6
+ it_behaves_like "function",
7
+ mapping: {
8
+ # flat hash
9
+ [{a: 1, b: 2}] => {[:a] => 1, [:b] => 2},
10
+
11
+ # flat array
12
+ [ [:a, :b, :c] ] => {
13
+ [0] => :a,
14
+ [1] => :b,
15
+ [2] => :c,
16
+ },
17
+
18
+ # Nested, all hashes
19
+ [{
20
+ a: {
21
+ x: 'ex',
22
+ y: {
23
+ z: 'zee'
24
+ }
25
+ },
26
+ b: 'bee',
27
+ }] => {
28
+ [:a, :x] => 'ex',
29
+ [:a, :y, :z] => 'zee',
30
+ [:b] => 'bee',
31
+ },
32
+
33
+ # Mixed arrays and hashes
34
+ [{
35
+ 1 => {
36
+ name: 'Neil',
37
+ likes: ['tacos', 'cats'],
38
+ },
39
+
40
+ 2 => {
41
+ name: 'Mica',
42
+ likes: ['cats', 'cookies'],
43
+ },
44
+ }] => {
45
+ [1, :name] => 'Neil',
46
+ [1, :likes, 0] => 'tacos',
47
+ [1, :likes, 1] => 'cats',
48
+ [2, :name] => 'Mica',
49
+ [2, :likes, 0] => 'cats',
50
+ [2, :likes, 1] => 'cookies',
51
+ },
52
+
53
+ # Sets should be considered leaves
54
+ [{
55
+ neil: {
56
+ name: 'Neil',
57
+ likes: Set['tacos', 'cats'],
58
+ },
59
+ }] => {
60
+ [:neil, :name] => 'Neil',
61
+ [:neil, :likes] => Set['tacos', 'cats'],
62
+ },
63
+ } # mapping
64
+
65
+ end # NRSER.leaves
66
+
67
+ describe "NRSER.map_leaves" do
68
+ let( :source ) {
69
+ {
70
+ 1 => {
71
+ name: 'Neil',
72
+ likes: ['tacos', 'cats'],
73
+ },
74
+
75
+ 2 => {
76
+ name: 'Mica',
77
+ likes: ['cats', 'cookies'],
78
+ },
79
+ }
80
+ }
81
+
82
+ subject {
83
+ NRSER.map_leaves( source ) { |key_path, value|
84
+ case value
85
+ when 'tacos'
86
+ 'tamales'
87
+ when 'cats'
88
+ 'bats'
89
+ when 'cookies'
90
+ 'wookies'
91
+ else
92
+ value
93
+ end
94
+ }
95
+ }
96
+
97
+ it {
98
+ is_expected.to eq({
99
+ 1 => {
100
+ name: 'Neil',
101
+ likes: ['tamales', 'bats'],
102
+ },
103
+
104
+ 2 => {
105
+ name: 'Mica',
106
+ likes: ['bats', 'wookies'],
107
+ },
108
+ })
109
+ }
110
+
111
+ end # NRSER.map_leaves
112
+
@@ -0,0 +1,165 @@
1
+ require 'spec_helper'
2
+
3
+ require 'nrser/refinements'
4
+ using NRSER
5
+
6
+ describe "NRSER.transform" do
7
+ subject { NRSER.transform tree, source }
8
+
9
+ describe_section "Simple Examples" do
10
+ # ========================================================================
11
+
12
+ describe "value swap in {x: 'ex', y: 'why?'}" do
13
+
14
+ let( :tree ) {
15
+ {
16
+ x: :y.retriever,
17
+ y: :x.retriever,
18
+ }
19
+ } # let :tree
20
+
21
+ let( :source ) {
22
+ {
23
+ x: 'ex',
24
+ y: 'why?'
25
+ }
26
+ } # let :source
27
+
28
+ it { is_expected.to eq x: 'why?', y: 'ex' }
29
+
30
+ end # value swap in {x: 'ex', y: 'why?'}
31
+
32
+
33
+ describe "transform in key" do
34
+
35
+ let :tree do
36
+ {
37
+ users: {
38
+ { id: :id.retriever } => {
39
+ name: :name.retriever,
40
+ }
41
+ }
42
+ }
43
+ end
44
+
45
+ let :source do
46
+ {
47
+ id: 123,
48
+ name: "Mr. Cat",
49
+ }
50
+ end
51
+
52
+ it do
53
+ is_expected.to eq \
54
+ users: {
55
+ { id: 123 } => {
56
+ name: "Mr. Cat",
57
+ }
58
+ }
59
+ end
60
+
61
+ end # transform in key
62
+
63
+ # TODO doesn't work yet... prob wants a general {NRSER#map_branches} or
64
+ # something that converts the map result into a Hash only if the
65
+ # tree was hash-like.
66
+ #
67
+ # describe "arrays in tree" do
68
+ # let :tree do
69
+ # {
70
+ # list: [
71
+ # { name: :name.rtvr },
72
+ # { age: :age.rtvr },
73
+ # ]
74
+ # }
75
+ # end
76
+ #
77
+ # let :source do
78
+ # {
79
+ # name: 'Mr. Cat',
80
+ # age: 2,
81
+ # }
82
+ # end
83
+ #
84
+ # it do
85
+ # is_expected.to eq \
86
+ # list: [
87
+ # { name: 'Mr. Cat' },
88
+ # { age: 2 },
89
+ # ]
90
+ # end
91
+ # end # arrays in tree
92
+
93
+
94
+ end # section simple examples
95
+ # ************************************************************************
96
+
97
+
98
+ describe_section "Real-World Examples" do
99
+ # ========================================================================
100
+
101
+ describe "Address" do
102
+
103
+ let :contact do
104
+ OpenStruct.new id: 123
105
+ end
106
+
107
+ let :address do
108
+ OpenStruct.new \
109
+ id: 987,
110
+ parent: contact,
111
+ address: "东城区",
112
+ street2: "民安小区",
113
+ city: "北京市",
114
+ state: "北京",
115
+ zip: "100010"
116
+ end
117
+
118
+ let :source do
119
+ address
120
+ end
121
+
122
+ let :tree do
123
+ {
124
+ users: {
125
+ { contact_id: [ :parent, :id ].chainer } => {
126
+ addresses: {
127
+ {
128
+ address_id: [ :id ].sender } => {
129
+ district: :address.retriever,
130
+ line_1: :street2.retriever,
131
+ city: :city.retriever,
132
+ province: :state.retriever,
133
+ post_code: :zip.retriever,
134
+ }
135
+ }
136
+ }
137
+ }
138
+ }
139
+ end
140
+
141
+ it do
142
+ is_expected.to eq \
143
+ users: {
144
+ { contact_id: 123 } => {
145
+ addresses: {
146
+ { address_id: 987 } => {
147
+ district: "东城区",
148
+ line_1: "民安小区",
149
+ city: "北京市",
150
+ province: "北京",
151
+ post_code: "100010",
152
+ }
153
+ }
154
+ }
155
+ }
156
+ end
157
+
158
+ end # Address
159
+
160
+ end # section Real-World Examples
161
+ # ************************************************************************
162
+
163
+
164
+ end # NRSER.transform
165
+