y_support 2.1.18 → 2.4.4

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 (57) hide show
  1. checksums.yaml +4 -4
  2. data/lib/y_support/all.rb +2 -32
  3. data/lib/y_support/core_ext/array.rb +2 -2
  4. data/lib/y_support/core_ext/class.rb +2 -2
  5. data/lib/y_support/core_ext/enumerable.rb +2 -2
  6. data/lib/y_support/core_ext/hash/misc.rb +23 -10
  7. data/lib/y_support/core_ext/hash.rb +2 -2
  8. data/lib/y_support/core_ext/module/misc.rb +9 -0
  9. data/lib/y_support/core_ext/module.rb +2 -2
  10. data/lib/y_support/core_ext/numeric.rb +2 -2
  11. data/lib/y_support/core_ext/object/inspection.rb +8 -2
  12. data/lib/y_support/core_ext/object.rb +3 -3
  13. data/lib/y_support/core_ext/string/misc.rb +9 -12
  14. data/lib/y_support/core_ext/string.rb +2 -2
  15. data/lib/y_support/core_ext/symbol.rb +2 -2
  16. data/lib/y_support/core_ext.rb +1 -1
  17. data/lib/y_support/flex_coerce/class_methods.rb +49 -0
  18. data/lib/y_support/flex_coerce/flex_proxy.rb +121 -0
  19. data/lib/y_support/flex_coerce/module_methods.rb +37 -0
  20. data/lib/y_support/flex_coerce.rb +24 -0
  21. data/lib/y_support/kde.rb +1 -1
  22. data/lib/y_support/literate.rb +253 -0
  23. data/lib/y_support/local_object.rb +1 -1
  24. data/lib/y_support/name_magic/array_methods.rb +48 -0
  25. data/lib/y_support/name_magic/class_methods.rb +205 -161
  26. data/lib/y_support/name_magic/hash_methods.rb +33 -0
  27. data/lib/y_support/name_magic/namespace.rb +449 -0
  28. data/lib/y_support/name_magic.rb +358 -100
  29. data/lib/y_support/null_object.rb +1 -1
  30. data/lib/y_support/respond_to.rb +1 -1
  31. data/lib/y_support/stdlib_ext/matrix/misc.rb +2 -2
  32. data/lib/y_support/stdlib_ext/matrix.rb +2 -2
  33. data/lib/y_support/stdlib_ext.rb +1 -1
  34. data/lib/y_support/typing/array.rb +1 -1
  35. data/lib/y_support/typing/enumerable.rb +1 -1
  36. data/lib/y_support/typing/hash.rb +1 -1
  37. data/lib/y_support/typing/module.rb +1 -1
  38. data/lib/y_support/typing/object/typing.rb +17 -15
  39. data/lib/y_support/typing/object.rb +1 -1
  40. data/lib/y_support/typing.rb +14 -10
  41. data/lib/y_support/unicode.rb +1 -1
  42. data/lib/y_support/version.rb +1 -1
  43. data/lib/y_support/x.rb +2 -1
  44. data/test/flex_coerce_test.rb +134 -0
  45. data/test/literate_test.rb +231 -0
  46. data/test/misc_test.rb +49 -27
  47. data/test/name_magic_test.rb +907 -60
  48. data/test/typing_test.rb +7 -7
  49. metadata +14 -13
  50. data/lib/y_support/abstract_algebra.rb +0 -234
  51. data/lib/y_support/name_magic/array.rb +0 -38
  52. data/lib/y_support/name_magic/hash.rb +0 -31
  53. data/lib/y_support/name_magic/namespace_methods.rb +0 -260
  54. data/lib/y_support/try.rb +0 -133
  55. data/test/abstract_algebra_test.rb +0 -138
  56. data/test/performance_test_example.rb +0 -23
  57. data/test/try_test.rb +0 -102
@@ -1,6 +1,8 @@
1
1
  require 'active_support/core_ext/object/blank'
2
- require File.dirname( __FILE__ ) + '/../../core_ext/object/inspection'
3
- require File.dirname( __FILE__ ) + '/../../core_ext/string/misc'
2
+ # require File.dirname( __FILE__ ) + '/../../core_ext/object/inspection'
3
+ # require File.dirname( __FILE__ ) + '/../../core_ext/string/misc'
4
+ require_relative '../../core_ext/object/inspection'
5
+ require_relative '../../core_ext/string/misc'
4
6
 
5
7
  class Object
6
8
  # === Typing by declaration
@@ -46,7 +48,7 @@ class Object
46
48
  # the receiver (using +#instance_exec+ method). If no block is given, it is
47
49
  # checked, whether the object is truey.
48
50
  #
49
- def aT what_is_receiver=insp, how_comply=nil, &b
51
+ def aT what_is_receiver=y_inspect, how_comply=nil, &b
50
52
  return tap { fail TypeError unless self } unless b
51
53
  return self if b.( self )
52
54
  m = "%s fails " + ( how_comply ? "to #{how_comply}" : "its check" )
@@ -62,7 +64,7 @@ class Object
62
64
  # inside the singleton class of the receiver (using #instance_exec method). If
63
65
  # no block is given, it is checked, whether the object is falsey.
64
66
  #
65
- def aT_not what_is_receiver=insp, how_comply=nil, &b
67
+ def aT_not what_is_receiver=y_inspect, how_comply=nil, &b
66
68
  return tap { fail TypeError if self } unless b
67
69
  return self unless b.( self )
68
70
  m = how_comply ? "%s must not #{how_comply}" : "%s fails its check"
@@ -72,7 +74,7 @@ class Object
72
74
  # Fails with +TypeError+ unless the receiver is of the prescribed class. Second
73
75
  # optional argument customizes the error message (receiver description).
74
76
  #
75
- def aT_kind_of klass, what_is_receiver=insp
77
+ def aT_kind_of klass, what_is_receiver=y_inspect
76
78
  return self if is_a? klass
77
79
  fail TypeError, "%s not a #{klass}".X!( what_is_receiver )
78
80
  end
@@ -82,7 +84,7 @@ class Object
82
84
  # given class, or is a descendant of that class. Second optional argument
83
85
  # customizes the error message (receiver description).
84
86
  #
85
- def aT_complies klass, what_is_receiver=insp
87
+ def aT_complies klass, what_is_receiver=y_inspect
86
88
  return self if class_complies? klass
87
89
  fail TypeError, "%s does not comply with #{klass}".X!( what_is_receiver )
88
90
  end
@@ -91,7 +93,7 @@ class Object
91
93
  # Fails with +TypeError+ unless the receiver responds to the given method.
92
94
  # Second optional argument customizes the error message (receiver description).
93
95
  #
94
- def aT_respond_to method_name, what_is_receiver=insp
96
+ def aT_respond_to method_name, what_is_receiver=y_inspect
95
97
  return self if respond_to? method_name
96
98
  fail TypeError,
97
99
  "%s does not respond to '#{method_name}'".X!( what_is_receiver )
@@ -102,9 +104,9 @@ class Object
102
104
  # equal to the argument. Two more optional arguments customize the error
103
105
  # message (receiver description and the description of the other object).
104
106
  #
105
- def aT_equal other, what_is_receiver=insp, what_is_other=nil
107
+ def aT_equal other, what_is_receiver=y_inspect, what_is_other=nil
106
108
  return self if self == other
107
- wo = what_is_other || "the prescribed value (#{other.insp})"
109
+ wo = what_is_other || "the prescribed value (#{other.y_inspect})"
108
110
  fail TypeError, "%s must be equal to %s".X!( [ what_is_receiver, wo ] )
109
111
  end
110
112
 
@@ -112,37 +114,37 @@ class Object
112
114
  # differs from to the argument. Two more optional arguments customize the error
113
115
  # message (receiver description and the description of the other object).
114
116
  #
115
- def aT_not_equal other, what_is_receiver=insp, what_is_other=nil
117
+ def aT_not_equal other, what_is_receiver=y_inspect, what_is_other=nil
116
118
  return self unless self == other
117
- wo = what_is_other || "the prescribed value (#{other.insp})"
119
+ wo = what_is_other || "the prescribed value (#{other.y_inspect})"
118
120
  fail TypeError, "%s must not == %s".X!( [ what_is_receiver, wo ] )
119
121
  end
120
122
 
121
123
  # Fails with +TypeError+ unless activesupport's +#blank+ returns true for
122
124
  # the receiver.
123
125
  #
124
- def aT_blank what_is_receiver=insp
126
+ def aT_blank what_is_receiver=y_inspect
125
127
  tap { blank? or fail TypeError, "%s not blank".X!( what_is_receiver ) }
126
128
  end
127
129
 
128
130
  # Fails with +TypeError+ unless activesupport's +#present+ returns true for
129
131
  # the receiver.
130
132
  #
131
- def aT_present what_is_receiver=insp
133
+ def aT_present what_is_receiver=y_inspect
132
134
  tap { present? or fail TypeError, "%s not present".X!( what_is_receiver ) }
133
135
  end
134
136
 
135
137
  # Fails with +ArgumentError+ unless the +ActiveSupport+ method +#blank+ returns
136
138
  # true for the receiver.
137
139
  #
138
- def aA_blank what_is_receiver=insp
140
+ def aA_blank what_is_receiver=y_inspect
139
141
  tap { blank? or fail ArgumentError, "%s not blank".X!( what_is_receiver ) }
140
142
  end
141
143
 
142
144
  # Fails with +ArgumentError+ unless the +ActiveSupport+ method #present returns
143
145
  # true for the receiver.
144
146
  #
145
- def aA_present what_is_receiver=insp
147
+ def aA_present what_is_receiver=y_inspect
146
148
  tap {
147
149
  present? or fail ArgumentError, "%s not present".X!( what_is_receiver )
148
150
  }
@@ -1 +1 @@
1
- require File.dirname( __FILE__ ) + '/object/typing'
1
+ require_relative 'object/typing'
@@ -1,21 +1,25 @@
1
1
  # encoding: utf-8
2
2
 
3
- require 'y_support'
3
+ require_relative '../y_support'
4
4
 
5
5
  # Typing library.
6
6
  #
7
- # Apart from typing objects <em>by class and ancestry</em> (+#kind_of?+),
8
- # y_support typing library provides support for typing <em>by declaration</em>,
9
- # and for runtime assertions.
7
+ # A collection of helper methods mainly for argument validation. We often want
8
+ # to validate that arguments are of certain class, or that they fulfill some
9
+ # other criteria, and raise sufficiently informative error messages when not.
10
+ # I've been also experimenting with what I call "typing by declaration", that
11
+ # is, when a class declares compliance with another class without actually
12
+ # being its descendant, but this idea is still experimental. Basically,
13
+ # 'y_support/typing' remains a library of runtime assertions.
10
14
 
11
15
  directories_to_look_in = [ :typing ]
12
16
 
13
- # The fololowing code looks into the specified directory(ies) and requires
17
+ # The following code looks into the specified directory(ies) and requires
14
18
  # all the files in it (them).
15
19
  #
16
- directories_to_look_in.each do |part|
17
- Dir["#{File.dirname( __FILE__ )}/#{part}/*/typing.rb"].sort.each { |path|
18
- dir = File.dirname( path ).match( "y_support/#{part}" ).post_match
19
- require "y_support/#{part}#{dir}/typing"
20
- }
20
+ directories_to_look_in.each do |name|
21
+ Dir["#{File.dirname( __FILE__ )}/#{name}/*/typing.rb"].sort.each do |path|
22
+ dir = File.dirname( path ).match( "y_support/#{name}" ).post_match
23
+ require_relative "#{name}#{dir}/typing"
24
+ end
21
25
  end
@@ -1,6 +1,6 @@
1
1
  # encoding: utf-8
2
2
 
3
- require 'y_support'
3
+ require_relative '../y_support'
4
4
 
5
5
  # +y_support/unicode+ defines a small number of Unicode 1-character aliases to
6
6
  # make code more concise.
@@ -1,4 +1,4 @@
1
1
  module YSupport
2
- VERSION = "2.1.18"
2
+ VERSION = "2.4.4"
3
3
  DEBUG = false
4
4
  end
data/lib/y_support/x.rb CHANGED
@@ -1,4 +1,5 @@
1
- require 'y_support'
1
+ require 'gtk2'
2
+ require_relative '../y_support'
2
3
 
3
4
  # Assets related to X windows control.
4
5
  #
@@ -0,0 +1,134 @@
1
+ #! /usr/bin/ruby
2
+ # encoding: utf-8
3
+
4
+ require 'minitest/autorun'
5
+ require_relative '../lib/y_support/flex_coerce'
6
+
7
+ describe "user class that defines no coercion whatsoever" do
8
+ before do
9
+ @c = Class.new do include FlexCoerce end
10
+ end
11
+
12
+ it "must be extended by FlexCoerce::ClassMethods" do
13
+ @c.singleton_class.ancestors.must_include FlexCoerce::ClassMethods
14
+ end
15
+
16
+ it "must have a parametrized subclass of FlexProxy" do
17
+ assert @c.FlexProxy < FlexCoerce::FlexProxy
18
+ @c.FlexProxy.host_class.must_equal @c
19
+ end
20
+
21
+ describe "object of that class" do
22
+ before do
23
+ @object = @c.new
24
+ end
25
+
26
+ it "should provide to the user class #coerce method returning a proxy" do
27
+ o1, o2 = @object.coerce 42
28
+ o1.must_be_kind_of FlexCoerce::FlexProxy
29
+ o2.must_equal @object
30
+ end
31
+
32
+ it "should raise TypeError for all operators and binary methods" do
33
+ -> { 42 + @object }.must_raise TypeError
34
+ -> { 42 - @object }.must_raise TypeError
35
+ -> { 42 * @object }.must_raise TypeError
36
+ -> { 42 / @object }.must_raise TypeError
37
+ -> { 42 % @object }.must_raise TypeError
38
+ -> { 42.div @object }.must_raise TypeError
39
+ -> { 42.divmod @object }.must_raise TypeError
40
+ -> { 42.fdiv @object }.must_raise TypeError
41
+ -> { 42 ** @object }.must_raise TypeError
42
+ -> { 42 & @object }.must_raise TypeError
43
+ -> { 42 | @object }.must_raise TypeError
44
+ -> { 42 ^ @object }.must_raise TypeError
45
+ -> { 42 > @object }.must_raise TypeError
46
+ -> { 42 >= @object }.must_raise TypeError
47
+ -> { 42 < @object }.must_raise TypeError
48
+ -> { 42 <= @object }.must_raise TypeError
49
+ -> { 42 <=> @object }.must_raise TypeError
50
+ # Operator #=== is too liberal to call #coerce.
51
+ -> { @object.coerce( 42 ).first === @object }.must_raise TypeError
52
+ end
53
+ end
54
+ end
55
+
56
+ describe "user class that allows Numeric#* and nothing else" do
57
+ before do
58
+ @c = Class.new do
59
+ include FlexCoerce
60
+ def + number; 10 + number end
61
+ def - number; 10 - number end
62
+ def * number; 10 * number end
63
+ def / number; 10 / number end
64
+ end
65
+
66
+ @c.define_coercion Fixnum, method: :* do |left_operand, right_operand|
67
+ right_operand * left_operand
68
+ end
69
+ end
70
+
71
+ it "must have coercion table with :* entry" do
72
+ @c.coercion_table.keys.must_equal [ :* ]
73
+ table_entry = @c.FlexProxy.new( 42 ).host_class.coercion_table[ :* ]
74
+ table_entry.size.must_equal 1
75
+ table_entry.find { |type, closure| type === 42 }.must_be_kind_of Array
76
+ assert table_entry.find { |type, _| type == :foobar }.nil?
77
+ end
78
+
79
+ describe "object of that class" do
80
+ before do
81
+ @object = @c.new
82
+ end
83
+
84
+ it "is defined to behave as number 10 with 4 basic operators" do
85
+ ( @object + 2 ).must_equal 12
86
+ ( @object - 2 ).must_equal 8
87
+ ( @object * 2 ).must_equal 20
88
+ ( @object / 2 ).must_equal 5
89
+ end
90
+
91
+ it "must have working coercion with Fixnum#*, but not other classes" do
92
+ ( 2 * @object ).must_equal 20
93
+ ( 3 * @object ).must_equal 30
94
+ -> { 3.0 * @object }.must_raise TypeError
95
+ end
96
+
97
+ it "should not define coercion for other operators" do
98
+ -> { 42 + @object }.must_raise TypeError
99
+ -> { 42 - @object }.must_raise TypeError
100
+ -> { 42 / @object }.must_raise TypeError
101
+ -> { 42 % @object }.must_raise TypeError
102
+ end
103
+ end
104
+ end
105
+
106
+ describe "class that includes FlexCoerce via another module" do
107
+ before do
108
+ m = Module.new do include FlexCoerce end
109
+ @c = Class.new do
110
+ include m
111
+ def + arg; 10 + arg end
112
+ end
113
+ end
114
+
115
+ it "should still allow defining coercion" do
116
+ @c.methods.must_include :define_coercion
117
+ end
118
+
119
+ describe "object of such class" do
120
+ before do
121
+ @c.define_coercion Integer, method: :+ do |operand_1, operand_2|
122
+ operand_2 + operand_1
123
+ end
124
+ @object = @c.new
125
+ end
126
+
127
+ it "should function as expected" do
128
+ ( 1 + @c.new ).must_equal 11
129
+ end
130
+ end
131
+ end
132
+
133
+
134
+
@@ -0,0 +1,231 @@
1
+ #! /usr/bin/ruby
2
+ # coding: utf-8
3
+
4
+ require 'minitest/autorun'
5
+ # require 'y_support/literate' # tested component itself
6
+ require './../lib/y_support/literate'
7
+
8
+ describe Literate::Attempt do
9
+ before do
10
+ @str = "lorem ipsum dolor sit amet"
11
+ @txt = "split the sentence into words"
12
+ # A simple attempt block.
13
+ @a = Literate::Attempt.new subject: @str, text: @txt do
14
+ note is: "natural language sentence"
15
+ split ' '
16
+ end
17
+ # More verbose attempt block.
18
+ chosen_word = 3
19
+ @b = Literate::Attempt.new subject: @str, text: @txt do
20
+ » is: "natural language sentence"
21
+ » has: "#{size} characters"
22
+ words = split ' '
23
+ » "number of words", is: words.size
24
+ » "chosen word", is: words[ chosen_word ]
25
+ words
26
+ end
27
+ end
28
+
29
+ it "should have 4 basic properties" do
30
+ @a.__text__.must_equal @txt
31
+ @a.__subject__.must_equal @str
32
+ @a.__block__.must_be_kind_of Proc
33
+ @a.__knowledge_base__.must_be_empty
34
+ # Fact list is empty because the block hasn't been run yet.
35
+ # Let's run the block:
36
+ @a.__run__
37
+ # Now the fact list includes the comment made in the block.
38
+ @a.__knowledge_base__.size.must_equal 1
39
+ end
40
+
41
+ describe "#__run__" do
42
+ it "must run the attempt's block" do
43
+ expected_result = "lorem", "ipsum", "dolor", "sit", "amet"
44
+ @a.__run__.must_equal expected_result
45
+ end
46
+ end
47
+
48
+ describe "Object#try method" do
49
+ before do
50
+ error = false
51
+ @error_switch = -> arg { error = arg }
52
+ @text = "to split into words"
53
+ @block = proc do
54
+ note is: "a string with several words"
55
+ fail error if error
56
+ split ' '
57
+ end
58
+ end
59
+
60
+ it "must execute the block allowing subject's methods" do
61
+ "hello world".try( @text, &@block )
62
+ .must_equal [ "hello", "world" ]
63
+ @error_switch.( TypeError )
64
+ -> { "hello world".try @text, &@block }.must_raise TypeError
65
+ @error_switch.( NameError )
66
+ -> { "hello world".try @text, &@block }.must_raise NameError
67
+ end
68
+
69
+ it "must allow Literate::Attempt#comment inside the block" do
70
+ begin
71
+ @error_switch.( TypeError )
72
+ "hello world".try @text, &@block
73
+ rescue => error
74
+ # Proof that Literate::Attemp#comment activated.
75
+ m = error.message
76
+ m.must_include "When trying to split into words"
77
+ m.must_include "a string with several words"
78
+ else
79
+ flunk "Error expected but nothing raised!"
80
+ end
81
+ end
82
+ end
83
+
84
+ describe "#note" do
85
+ it "must write entries into @__knowledge_base__" do
86
+ @a.__run__
87
+ x = { @str => [ is: "natural language sentence" ] }
88
+ @a.__knowledge_base__.must_equal x
89
+ end
90
+
91
+ it "must write entries into @__knowledge_base__" do
92
+ @b.__run__
93
+ x = { @str => [ is: "natural language sentence",
94
+ has: "26 characters" ],
95
+ "number of words" => [ is: 5 ],
96
+ "chosen word" => [ is: "sit" ] }
97
+ @b.__knowledge_base__ .must_equal x
98
+ end
99
+ end
100
+
101
+ describe "#__describe__" do
102
+ it "must produce description of the main subject" do
103
+ @a.__run__
104
+ @a.__describe__( @a.__subject__ )
105
+ .must_equal [ "lorem ipsum dolor sit amet",
106
+ { is: "natural language sentence" } ]
107
+ @b.__run__
108
+ @b.__describe__( @a.__subject__ )
109
+ .must_equal [ "lorem ipsum dolor sit amet",
110
+ { is: "natural language sentence",
111
+ has: "26 characters" } ]
112
+ end
113
+ end
114
+
115
+ describe "#__circumstances__" do
116
+ it "..." do
117
+ @a.__run__
118
+ @a.__circumstances__.must_equal ""
119
+ @b.__run__
120
+ @b.__circumstances__
121
+ .must_equal "number of words being 5, " +
122
+ "chosen word being sit"
123
+ end
124
+ end
125
+ end
126
+
127
+ describe "usecase 1: name validator" do
128
+ before do
129
+ @name_validator = Object.new
130
+ @name_validator.define_singleton_method :validate do |name|
131
+ name.to_s.try "to validate the requested name" do
132
+ note "rejecting non-capitalized names"
133
+ fail NameError unless ( ?A..?Z ) === self[0]
134
+ note "rejecting names with spaces"
135
+ fail NameError unless split( ' ' ).size == 1
136
+ end
137
+ return name
138
+ end
139
+ end
140
+
141
+ it "should validate good names" do
142
+ @name_validator.validate( :Fred ).must_equal :Fred
143
+ @name_validator.validate( "Su_san" ).must_equal "Su_san"
144
+ end
145
+
146
+ it "should reject bad names with a good error message" do
147
+ expected_message =
148
+ "When trying to validate the requested name, rejecting " +
149
+ "non-capitalized names: NameError!"
150
+ begin
151
+ @name_validator.validate( :fred )
152
+ rescue => error
153
+ error.message.must_equal expected_message
154
+ end
155
+ end
156
+ end
157
+
158
+ # describe 'case 1' do
159
+ # it "should work" do
160
+ # # begin
161
+ # # @a.__run__
162
+ # # rescue TypeError => err
163
+ # # expected_msg = "When trying concatenation of an array " +
164
+ # # "with 2 elements, TypeError occurred: " +
165
+ # # "Lorem ipsum dolor sit amet!"
166
+ # # # Make sure the last 45 characters is OK.
167
+ # # assert_equal expected_msg[-45..-1], err.message[-45..-1]
168
+ # # # # Make sure that whole message is as expected.
169
+ # # # assert_equal expected_msg, err.message
170
+ # # else
171
+ # # flunk "Expected TypeError error not raised!"
172
+ # # end
173
+ # end
174
+ # end
175
+
176
+ # describe 'case 2' do
177
+ # it "should work" do
178
+ # begin
179
+ # try "to call constant Nothing" do Nothing end
180
+ # rescue NameError => err
181
+ # expected_msg = 'When trying to call constant Nothing, ' +
182
+ # 'NameError occurred: uninitialized constant Nothing'
183
+ # assert_equal( expected_msg, err.message )
184
+ # else
185
+ # flunk "Expected NameError error not raised!"
186
+ # end
187
+ # end
188
+ # end
189
+
190
+ # describe 'case 3' do
191
+ # it "should work" do
192
+ # o = Object.new
193
+ # class << o
194
+ # def to_s; "THIS OBJECT" end
195
+ # def hello!; "hello hello" end
196
+ # end
197
+ # # Object's methods must be callable
198
+ # o.try "to say hello" do hello! end.must_equal "hello hello"
199
+ # begin
200
+ # o.try "to call a weird method" do goodbye! end
201
+ # rescue NoMethodError => err
202
+ # err.message.must_include "When trying to call a weird " +
203
+ # "method, NoMethodError occurred: undefined method"
204
+ # err.message.must_include "goodbye!"
205
+ # end
206
+ # end
207
+ # end
208
+
209
+ # describe 'case 4' do
210
+ # it "should work" do
211
+ # begin
212
+ # "FooBar".try "to do something" do
213
+ # comment has: "#{size} letters",
214
+ # is: "a #{self.class} instance"
215
+ # unless include? "Quux"
216
+ # comment "Quux", is: "not a part of it"
217
+ # try "to append Quux to it" do
218
+ # self << "Quux"
219
+ # fail "EPIC FAIL"
220
+ # end
221
+ # end
222
+ # end
223
+ # rescue => err
224
+ # err.message.must_equal "When trying to do something, " +
225
+ # "FooBar having 6 letters, being a String instance, " +
226
+ # "Quux being not a part of it, RuntimeError occurred: " +
227
+ # "When trying to append Quux to it, RuntimeError " +
228
+ # "occurred: EPIC FAIL"
229
+ # end
230
+ # end
231
+ # end
data/test/misc_test.rb CHANGED
@@ -29,6 +29,13 @@ describe Object do
29
29
  o.bar.ancestors[1].must_equal( m )
30
30
  o.bar.mother.must_equal( o )
31
31
  end
32
+
33
+ it "should have #insp method to facilitate inspection" do
34
+ module Quux; class Foo; def to_s; "bar" end end end
35
+ Quux::Foo.new.y_inspect.must_equal "Quux::Foo:bar"
36
+ Quux::Foo.new.y_inspect( :full ).must_equal "#<Quux::Foo:bar>"
37
+ Quux::Foo.new.y_inspect( :short ).must_equal "Foo:bar"
38
+ end
32
39
  end
33
40
 
34
41
 
@@ -52,7 +59,8 @@ describe Module do
52
59
  m.const_reset! :Foo, 43
53
60
  m::Foo.must_equal 43
54
61
  m.module_exec do
55
- def a; 42 end
62
+ selector :a
63
+ def initialize; @a = 42 end
56
64
  chain b: :a, &:to_s
57
65
  end
58
66
  Class.new do include m end.new.b.must_equal "42"
@@ -65,6 +73,14 @@ describe Class do
65
73
  require './../lib/y_support/core_ext/class'
66
74
  end
67
75
 
76
+ it "has #selector alias for #attr_reader method" do
77
+ o = Class.new do
78
+ selector :a
79
+ def initialize a; @a = a end
80
+ end.new( 42 )
81
+ o.a.must_equal( 42 )
82
+ end
83
+
68
84
  it "has #parametrize method" do
69
85
  a = Class.new
70
86
  -> { a.foo }.must_raise NoMethodError
@@ -174,32 +190,38 @@ describe Hash do
174
190
  test = { a: 11, b: 22 }
175
191
  assert_equal( { a: 11, b: 22 }, test.default!( defaults ) )
176
192
  test = { a: 11, c: 22 }
177
- assert_equal( { a: 11, b: nil, c: 22 }, test.default!( defaults ) )
178
- end
179
-
180
- it "should have #with_keys and #modify_keys" do
181
- assert_equal( {"a" => :b, "c" => :d}, {a: :b, c: :d}.with_keys( &:to_s ) )
182
- assert_equal( {"a1" => 1, "c2" => 2}, {a: 1, c: 2}.modify_keys { |k, v|
183
- k.to_s + v.to_s } )
184
- assert_equal( {"a1" => 1, "c2" => 2}, {a: 1, c: 2}.modify_keys {|p|
185
- p[0].to_s + p[1].to_s } )
186
- assert_equal( {2 => 1, 4 => 2}, {1 => 1, 2 => 2}.modify_keys { |k, v|
187
- k + v } )
188
- assert_equal( {2 => 1, 4 => 2}, {1 => 1, 2 => 2}.modify_keys { |p|
189
- p[0] + p[1] } )
190
- end
191
-
192
- it "should have #with_values and #modify_values" do
193
- assert_equal( { a: "b", c: "d" }, {a: :b, c: :d}.with_values( &:to_s ) )
194
- assert_equal( {a: "ab", c: "cd"}, {a: :b, c: :d}.modify_values { |k, v|
195
- k.to_s + v.to_s } )
196
- assert_equal( {a: "ab", c: "cd"}, {a: :b, c: :d}.modify_values { |p|
197
- p[0].to_s + p[1].to_s } )
198
- hh = { a: 1, b: 2 }
199
- hh.with_values! &:to_s
200
- assert_equal ["1", "2"], hh.values
201
- hh.modify_values! &:join
202
- assert_equal ["a1", "b2"], hh.values
193
+ { a: 11, b: nil, c: 22 }.must_equal test.default! defaults
194
+ end
195
+
196
+ it "should have #with_keys and #with_keys!" do
197
+ test = { "a" => :b, "c" => :d }
198
+ test.with_keys( &:to_sym ).must_equal( { a: :b, c: :d } )
199
+ test.must_equal( { "a" => :b, "c" => :d } )
200
+ test.with_keys! &:to_sym
201
+ test.must_equal( { a: :b, c: :d } )
202
+ end
203
+
204
+ it "should have #change_keys" do
205
+ test = { a: 1, c: 2 }
206
+ test.change_keys { |k, v| k.to_s + v.to_s }
207
+ .must_equal( { "a1" => 1, "c2" => 2 } )
208
+ end
209
+
210
+ it "should have #with_values and #with_values!" do
211
+ test = { a: :b, c: :d }
212
+ test.with_values( &:to_s ).must_equal( { a: "b", c: "d" } )
213
+ test.must_equal( { a: :b, c: :d } )
214
+ test.with_values!( &:to_s )
215
+ test.must_equal( { a: "b", c: "d" } )
216
+ end
217
+
218
+ it "should have #change_values and #change_values!" do
219
+ test = { a: :b, c: :d }
220
+ test.modify_values do |k, v| k.to_s + v.to_s end
221
+ .must_equal( {a: "ab", c: "cd"} )
222
+ test.must_equal( { a: :b, c: :d } )
223
+ test.modify_values! { |k, v| k.to_s + v.to_s }
224
+ test.must_equal( {a: "ab", c: "cd"} )
203
225
  end
204
226
 
205
227
  it "should have #modify" do