xqsr3 0.10.2 → 0.11.1

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 522223b0b707f9057fdafa48580809911ecd8c9d
4
- data.tar.gz: 9203708c9ca41f78025c5882f72fa7f55170a095
3
+ metadata.gz: b23c1bd7f01f0540f8cd11ba2a619fa6d2fb334c
4
+ data.tar.gz: 7b79521e19d9f76bc869a83c8003cbddec3ad576
5
5
  SHA512:
6
- metadata.gz: fcb1fb10938327574cb3ea10ce57a91d795d6cc524cd95aae6770daace4306ae63f17957920bb3e32932ce11f350139cc70151485a38b86f072622b7c34260e4
7
- data.tar.gz: 4aef021764d9cff5977379ae18136713cbbcb346afd87014de9f2dffd31e25e03aa51899494a6940af39d44ebd637a49b4145d52e940be7556ef93035ee95665
6
+ metadata.gz: 1c53ef621526a41f9f47afe099d1ff8df7dc775700a2974ecab2834a317f31fd012c98c679aa1499fb2ce696daf9f257ddf64424fa232517a6df0cff3383c212
7
+ data.tar.gz: bc62c09071304cb569e896217f719337038c5e888882b35ecdec4df67eb4c89202e8f6d896d12d9788918428888297fc87895b2b21dd998a737fb369008e56e1
@@ -0,0 +1,8 @@
1
+
2
+ require 'xqsr3/hash_utilities/deep_transform'
3
+
4
+ class Hash
5
+
6
+ include ::Xqsr3::HashUtilities::DeepTransform
7
+ end # class Hash
8
+
@@ -1,6 +1,7 @@
1
1
 
2
2
  require 'xqsr3/extensions/string/ends_with'
3
3
  require 'xqsr3/extensions/string/map_option_string'
4
+ require 'xqsr3/extensions/string/quote_if'
4
5
  require 'xqsr3/extensions/string/starts_with'
5
6
  require 'xqsr3/extensions/string/to_symbol'
6
7
 
@@ -0,0 +1,9 @@
1
+
2
+ require 'xqsr3/string_utilities/quote_if'
3
+
4
+ class String
5
+
6
+ include ::Xqsr3::StringUtilities::QuoteIf
7
+ end # class String
8
+
9
+
@@ -0,0 +1,155 @@
1
+
2
+ # ######################################################################## #
3
+ # File: lib/xqsr3/hash_utilities/deep_transform.rb
4
+ #
5
+ # Purpose: Definition of the ::Xqsr3::HashUtilities::DeepTransform
6
+ # module
7
+ #
8
+ # Created: 3rd June 2017
9
+ # Updated: 7th June 2017
10
+ #
11
+ # Home: http://github.com/synesissoftware/xqsr3
12
+ #
13
+ # Author: Matthew Wilson
14
+ #
15
+ # Copyright (c) 2017, Matthew Wilson and Synesis Software
16
+ # All rights reserved.
17
+ #
18
+ # Redistribution and use in source and binary forms, with or without
19
+ # modification, are permitted provided that the following conditions are
20
+ # met:
21
+ #
22
+ # * Redistributions of source code must retain the above copyright notice,
23
+ # this list of conditions and the following disclaimer.
24
+ #
25
+ # * Redistributions in binary form must reproduce the above copyright
26
+ # notice, this list of conditions and the following disclaimer in the
27
+ # documentation and/or other materials provided with the distribution.
28
+ #
29
+ # * Neither the names of the copyright holder nor the names of its
30
+ # contributors may be used to endorse or promote products derived from
31
+ # this software without specific prior written permission.
32
+ #
33
+ # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
34
+ # IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
35
+ # THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
36
+ # PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
37
+ # CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
38
+ # EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
39
+ # PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
40
+ # PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
41
+ # LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
42
+ # NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
43
+ # SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
44
+ #
45
+ # ######################################################################## #
46
+
47
+
48
+ # ##########################################################
49
+ # ::Xqsr3::HashUtilities::DeepTransform
50
+
51
+ =begin
52
+ =end
53
+
54
+ module Xqsr3
55
+ module HashUtilities
56
+
57
+ module DeepTransform
58
+
59
+ private
60
+ def self.do_deep_transform_on_hashlike_ h, &block
61
+
62
+ ::Xqsr3::Quality::ParameterChecking.check_parameter h, 'h', responds_to: [ :map ]
63
+
64
+ case block.arity
65
+ when 1
66
+
67
+ h =
68
+ Hash[h.map do |k, v|
69
+
70
+ k = k.deep_transform &block if ::Hash === k
71
+ v = v.deep_transform &block if ::Hash === v
72
+
73
+ [yield(k), v]
74
+ end]
75
+ when 2
76
+
77
+ h =
78
+ Hash[h.map do |k, v|
79
+
80
+ k = k.deep_transform &block if ::Hash === k
81
+ v = v.deep_transform &block if ::Hash === v
82
+
83
+ yield(k, v)
84
+ end]
85
+ else
86
+
87
+ raise ArgumentError, "block arity must be 1 or 2"
88
+ end
89
+
90
+ h
91
+ end
92
+
93
+ def do_deep_transform_on_self_ &block
94
+
95
+ ::Xqsr3::Quality::ParameterChecking.check_parameter h, 'h', responds_to: [ :[]=, :delete, :keys ]
96
+
97
+ case block.arity
98
+ when 1
99
+
100
+ self.keys.each do |k|
101
+
102
+ v = self.delete k
103
+
104
+ k = k.deep_transform &block if ::Hash === k
105
+ v = v.deep_transform &block if ::Hash === v
106
+
107
+ self[yield(k)] = v
108
+ end
109
+ when 2
110
+
111
+ self.keys.each do |k|
112
+
113
+ v = self.delete k
114
+
115
+ k = k.deep_transform &block if ::Hash === k
116
+ v = v.deep_transform &block if ::Hash === v
117
+
118
+ k, v = yield(k, v)
119
+ end
120
+ else
121
+
122
+ raise ArgumentError, "block arity must be 1 or 2"
123
+ end
124
+ end
125
+ public
126
+
127
+ # Executes the given mandatory 1- or 2-parameter block on the receiving
128
+ # instance, which must be a Hash or a type that responds to the +map+
129
+ # message, returning a copy of the instance in which keys (1-parameter
130
+ # block) or keys and values (2-parameter block) are transformed.
131
+ def deep_transform &block
132
+
133
+ DeepTransform.do_deep_transform_on_hashlike_ self, &block
134
+ end
135
+
136
+ # Executes the given mandatory 1- or 2-parameter block on the receiving
137
+ # instance, whihc must be a Hash or a type that responds to +[]+,
138
+ # +delete+, and +keys+ messages, changing the keys (1-parameter block)
139
+ # or keys and values (2-parameter block).
140
+ #
141
+ # @note This method is not strongly exception-safe - failure during
142
+ # transformation can result in a partially transformed instance
143
+ def deep_transform! &block
144
+
145
+ do_deep_transform_on_self_ &block
146
+ end
147
+
148
+ end # module DeepTransform
149
+
150
+ end # module HashUtilities
151
+ end # module Xqsr3
152
+
153
+ # ############################## end of file ############################# #
154
+
155
+
@@ -84,6 +84,8 @@ module ParameterChecking
84
84
  # of types, in which case +value+ may be an array that must
85
85
  # consist wholly of those types
86
86
  # @option +:values+ an array of values one of which +value+ must be
87
+ # @option +:responds_to+ an array of symbols specifying all messages to
88
+ # which the parameter will respond
87
89
  # @option +:reject_empty+ requires value to respond to +empty?+
88
90
  # message and to do so with false, unless +nil+
89
91
  # @option +:require_empty+ requires value to respond to +empty?+
@@ -135,6 +137,8 @@ module ParameterChecking
135
137
 
136
138
  unless value.nil?
137
139
 
140
+ # types
141
+
138
142
  types = options[:types] || []
139
143
  types = [value.class] if types.empty?
140
144
  type_found = false
@@ -192,6 +196,25 @@ module ParameterChecking
192
196
  raise TypeError, message
193
197
  end
194
198
  end
199
+
200
+
201
+ # messages
202
+
203
+ messages = options[:responds_to] || []
204
+
205
+ warn "#{self}::check_parameter: options[:responds_to] of type #{messages.class} - should be #{::Array}" unless messages.is_a?(Array)
206
+ warn "#{self}::check_parameter: options[:responds_to] should contain only symbols or strings" if messages.is_a?(::Array) && !messages.all? { |m| ::Symbol === m || ::String === m }
207
+
208
+ messages.each do |m|
209
+
210
+ unless value.respond_to? m
211
+
212
+ s_name = name.is_a?(String) ? "'#{name}' " : ''
213
+
214
+ raise TypeError, "#{param_s} #{s_name}(#{value.class}) must respond to the '#{m}' message"
215
+ end
216
+ end
217
+
195
218
  end
196
219
 
197
220
  # reject/require empty?
@@ -0,0 +1,132 @@
1
+
2
+ # ######################################################################## #
3
+ # File: lib/xqsr3/string_utilities/quote_if.rb
4
+ #
5
+ # Purpose: Definition of the ::Xqsr3::StringUtilities::QuoteIf
6
+ # module
7
+ #
8
+ # Created: 3rd June 2017
9
+ # Updated: 7th June 2017
10
+ #
11
+ # Home: http://github.com/synesissoftware/xqsr3
12
+ #
13
+ # Author: Matthew Wilson
14
+ #
15
+ # Copyright (c) 2017, Matthew Wilson and Synesis Software
16
+ # All rights reserved.
17
+ #
18
+ # Redistribution and use in source and binary forms, with or without
19
+ # modification, are permitted provided that the following conditions are
20
+ # met:
21
+ #
22
+ # * Redistributions of source code must retain the above copyright notice,
23
+ # this list of conditions and the following disclaimer.
24
+ #
25
+ # * Redistributions in binary form must reproduce the above copyright
26
+ # notice, this list of conditions and the following disclaimer in the
27
+ # documentation and/or other materials provided with the distribution.
28
+ #
29
+ # * Neither the names of the copyright holder nor the names of its
30
+ # contributors may be used to endorse or promote products derived from
31
+ # this software without specific prior written permission.
32
+ #
33
+ # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
34
+ # IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
35
+ # THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
36
+ # PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
37
+ # CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
38
+ # EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
39
+ # PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
40
+ # PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
41
+ # LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
42
+ # NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
43
+ # SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
44
+ #
45
+ # ######################################################################## #
46
+
47
+
48
+ # ##########################################################
49
+ # ::Xqsr3::StringUtilities::QuoteIf
50
+
51
+ =begin
52
+ =end
53
+
54
+ module Xqsr3
55
+ module StringUtilities
56
+
57
+ module QuoteIf
58
+
59
+ private
60
+ module QuoteIf_Helper_ #:nodoc:
61
+
62
+ def self.string_quote_if_array_ s, options
63
+
64
+ #$stderr.puts "#{self}#{__method__}(s (#{s.class})='#{s}', options (#{options.class})='#{options}'"
65
+
66
+ s = s.to_s unless String === s
67
+
68
+ quotes = options[:quotes] || [ '"', '"' ]
69
+ quotes = [ quotes, quotes ] if String === quotes
70
+
71
+ quotables = options[:quotables] || /\s/
72
+
73
+ #$stderr.puts "quotables (#{quotables.class}): [#{quotables}]"
74
+
75
+ case quotables
76
+ when ::String
77
+
78
+ return s unless s.include? quotables
79
+ when ::Array
80
+
81
+ return s unless quotables.any? { |quotable| s.include? quotable }
82
+ when ::Regexp
83
+
84
+ return s unless s =~ quotables
85
+ else
86
+
87
+ raise ArgumentError, "Invalid type (#{quotables.class}) specified for quotables parameter"
88
+ end
89
+
90
+ return quotes[0] + s + quotes[1]
91
+ end
92
+ end
93
+ public
94
+
95
+ # Converts a string to a quoted form if necessary
96
+ #
97
+ # === *Parameters*
98
+ #
99
+ # * *Required parameters*:
100
+ # - +s+:: [String] The string to be evaluated
101
+ #
102
+ # * *Options parameters*:
103
+ # - +options+:: [Hash] Options that control the behaviour of the
104
+ # method
105
+ #
106
+ # * *Options*:
107
+ #
108
+ # - +:quotes+:: [String, Array] A string that is used as the opening
109
+ # and closing quotes, or an array whose first two elements are
110
+ # used as the opening and closing quotes. Defaults to '"'
111
+ # - +:quotables+:: [String, Array, Regexp] A string representing the
112
+ # quotable character, or an array containing the quotable
113
+ # characters, or a regular expression that determines by match
114
+ # whether the string should be quoted. Defaults to the regular
115
+ # expression /\s/
116
+ def self.quote_if s, **options
117
+
118
+ QuoteIf_Helper_.string_quote_if_array_ s, options
119
+ end
120
+
121
+ def quote_if **options
122
+
123
+ QuoteIf_Helper_.string_quote_if_array_ self, options
124
+ end
125
+ end # module QuoteIf
126
+
127
+ end # module StringUtilities
128
+ end # module Xqsr3
129
+
130
+ # ############################## end of file ############################# #
131
+
132
+
@@ -5,7 +5,7 @@
5
5
  # Purpose: Version for Xqsr3 library
6
6
  #
7
7
  # Created: 3rd April 2016
8
- # Updated: 26th February 2017
8
+ # Updated: 7th June 2017
9
9
  #
10
10
  # Home: http://github.com/synesissoftware/xqsr3
11
11
  #
@@ -50,7 +50,7 @@
50
50
  module Xqsr3
51
51
 
52
52
  # Current version of the Xqsr3 library
53
- VERSION = '0.10.2'
53
+ VERSION = '0.11.1'
54
54
 
55
55
  private
56
56
  VERSION_PARTS_ = VERSION.split(/[.]/).collect { |n| n.to_i } # :nodoc:
@@ -0,0 +1,49 @@
1
+ #! /usr/bin/env ruby
2
+
3
+ $:.unshift File.join(File.dirname(__FILE__), '../../../../lib')
4
+
5
+ require 'xqsr3/extensions/hash/deep_transform'
6
+
7
+ require 'xqsr3/extensions/test/unit'
8
+ require 'test/unit'
9
+
10
+ require 'stringio'
11
+
12
+ class Test_Hash_deep_transform < Test::Unit::TestCase
13
+
14
+ def test_Hash_has_method
15
+
16
+ assert Hash.new.respond_to? :deep_transform
17
+ end
18
+
19
+ def test_with_empty
20
+
21
+ assert_equal Hash.new, Hash.new.deep_transform { |k| k }
22
+ assert_equal Hash.new, Hash.new.deep_transform { |k, v| [ k, v ] }
23
+ end
24
+
25
+ def test_transform_to_same
26
+
27
+ jkl = 12
28
+ h = { 'abc' => 'def', ghi: jkl, mno: { p: 'q', 'r' => 'st' } }
29
+
30
+ assert_equal h, h.deep_transform { |k| k }
31
+ assert_equal h, h.deep_transform { |k, v| [ k, v ] }
32
+ end
33
+
34
+ def test_transform_to_symbolise_keys
35
+
36
+ jkl = 12
37
+ h = { 'abc' => 'def', ghi: jkl, mno: { p: 'q', 'r' => 'st' } }
38
+
39
+ h_1 = { abc: 'def', ghi: jkl, mno: { p: 'q', r: 'st' } }
40
+ h_2 = { abc: :def, ghi: jkl, mno: { p: :q, r: :st } }
41
+
42
+ assert_equal h_1, h.deep_transform { |k| k.respond_to?(:to_sym) ? k.to_sym : k }
43
+ assert_equal h_1, h.deep_transform { |k, v| [ k.respond_to?(:to_sym) ? k.to_sym : k, v ] }
44
+ assert_equal h_2, h.deep_transform { |k, v| [ k.respond_to?(:to_sym) ? k.to_sym : k, v.respond_to?(:to_sym) ? v.to_sym : v ] }
45
+ end
46
+ end
47
+
48
+
49
+
@@ -0,0 +1,13 @@
1
+ #! /usr/bin/env ruby
2
+ #
3
+ # executes all other tests
4
+
5
+ this_file = File.expand_path(__FILE__)
6
+ this_dir = File.expand_path(File.dirname(__FILE__))
7
+
8
+ # all tc_*rb in current directory
9
+ Dir[File.join(this_dir, 'tc_*rb')].each { |file| require file }
10
+
11
+ # all ts_*rb in immediate sub-directories
12
+ Dir[File.join(this_dir, '*', 'ts_*rb')].each { |file| require file }
13
+
@@ -0,0 +1,42 @@
1
+ #! /usr/bin/env ruby
2
+
3
+ $:.unshift File.join(File.dirname(__FILE__), '../../../../lib')
4
+
5
+ require 'xqsr3/extensions/string/quote_if'
6
+
7
+ require 'xqsr3/extensions/test/unit'
8
+ require 'test/unit'
9
+
10
+ require 'stringio'
11
+
12
+ class Test_String_quote_if < Test::Unit::TestCase
13
+
14
+ def test_String_has_method
15
+
16
+ assert ''.respond_to? :quote_if
17
+ end
18
+
19
+ def test_with_no_options
20
+
21
+ assert_equal '', ''.quote_if
22
+ assert_equal 'a', 'a'.quote_if
23
+ assert_equal 'ab', 'ab'.quote_if
24
+ assert_equal '"a b"', 'a b'.quote_if
25
+ end
26
+
27
+ def test_with_quotables
28
+
29
+ assert_equal 'a b', 'a b'.quote_if(quotables: '-')
30
+ assert_equal '"a-b"', 'a-b'.quote_if(quotables: '-')
31
+ end
32
+
33
+ def test_with_quotes
34
+
35
+ assert_equal '"a b"', 'a b'.quote_if
36
+ assert_equal '|a b|', 'a b'.quote_if(quotes: '|')
37
+ assert_equal '[a b]', 'a b'.quote_if(quotes: [ '[', ']' ])
38
+ end
39
+ end
40
+
41
+
42
+
@@ -221,7 +221,23 @@ end
221
221
 
222
222
  assert(false, "wrong exception type #{x.class}) (with message '#{x.message}'")
223
223
  end
224
+ end
225
+
226
+
227
+ # responds_to
224
228
 
229
+ def check_responds_to a, messages, options = {}, &block
230
+
231
+ self.class.check_param a, 'a', options.merge({ responds_to: messages }), &block
232
+ end
233
+
234
+ def test_responds_to
235
+
236
+ assert check_responds_to Hash.new, [ :[], :map, :to_s ]
237
+ assert_raise ::TypeError do
238
+
239
+ check_responds_to Hash.new, [ :this_is_not_a_Hash_method ]
240
+ end
225
241
  end
226
242
  end
227
243
 
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: xqsr3
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.10.2
4
+ version: 0.11.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Matt Wilson
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2017-02-27 00:00:00.000000000 Z
11
+ date: 2017-06-07 00:00:00.000000000 Z
12
12
  dependencies: []
13
13
  description: |
14
14
  eXtensions by fine Quantum for Standard Ruby and 3rd-party libraries is a
@@ -29,6 +29,7 @@ files:
29
29
  - lib/xqsr3/extensions/enumerable.rb
30
30
  - lib/xqsr3/extensions/enumerable/collect_with_index.rb
31
31
  - lib/xqsr3/extensions/enumerable/unique.rb
32
+ - lib/xqsr3/extensions/hash/deep_transform.rb
32
33
  - lib/xqsr3/extensions/io.rb
33
34
  - lib/xqsr3/extensions/io/writelines.rb
34
35
  - lib/xqsr3/extensions/kernel.rb
@@ -36,16 +37,19 @@ files:
36
37
  - lib/xqsr3/extensions/string.rb
37
38
  - lib/xqsr3/extensions/string/ends_with.rb
38
39
  - lib/xqsr3/extensions/string/map_option_string.rb
40
+ - lib/xqsr3/extensions/string/quote_if.rb
39
41
  - lib/xqsr3/extensions/string/starts_with.rb
40
42
  - lib/xqsr3/extensions/string/to_symbol.rb
41
43
  - lib/xqsr3/extensions/test/unit.rb
42
44
  - lib/xqsr3/extensions/test/unit/assert_eql.rb
43
45
  - lib/xqsr3/extensions/test/unit/assert_not.rb
44
46
  - lib/xqsr3/extensions/test/unit/assert_not_eql.rb
47
+ - lib/xqsr3/hash_utilities/deep_transform.rb
45
48
  - lib/xqsr3/io/writelines.rb
46
49
  - lib/xqsr3/quality.rb
47
50
  - lib/xqsr3/quality/parameter_checking.rb
48
51
  - lib/xqsr3/string_utilities/ends_with.rb
52
+ - lib/xqsr3/string_utilities/quote_if.rb
49
53
  - lib/xqsr3/string_utilities/starts_with.rb
50
54
  - lib/xqsr3/string_utilities/to_symbol.rb
51
55
  - lib/xqsr3/version.rb
@@ -59,12 +63,15 @@ files:
59
63
  - test/unit/extensions/enumerable/tc_collect_with_index.rb
60
64
  - test/unit/extensions/enumerable/tc_unique.rb
61
65
  - test/unit/extensions/enumerable/ts_all.rb
66
+ - test/unit/extensions/hash/tc_deep_transform.rb
67
+ - test/unit/extensions/hash/ts_all.rb
62
68
  - test/unit/extensions/io/tc_writelines.rb
63
69
  - test/unit/extensions/io/ts_all.rb
64
70
  - test/unit/extensions/kernel/tc_raise_with_options.rb
65
71
  - test/unit/extensions/kernel/ts_all.rb
66
72
  - test/unit/extensions/string/tc_ends_with.rb
67
73
  - test/unit/extensions/string/tc_map_option_string.rb
74
+ - test/unit/extensions/string/tc_quote_if.rb
68
75
  - test/unit/extensions/string/tc_starts_with.rb
69
76
  - test/unit/extensions/string/tc_to_symbol.rb
70
77
  - test/unit/extensions/string/ts_all.rb