nrser 0.0.25 → 0.0.26

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