y_support 2.1.18 → 2.4.4
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/y_support/all.rb +2 -32
- data/lib/y_support/core_ext/array.rb +2 -2
- data/lib/y_support/core_ext/class.rb +2 -2
- data/lib/y_support/core_ext/enumerable.rb +2 -2
- data/lib/y_support/core_ext/hash/misc.rb +23 -10
- data/lib/y_support/core_ext/hash.rb +2 -2
- data/lib/y_support/core_ext/module/misc.rb +9 -0
- data/lib/y_support/core_ext/module.rb +2 -2
- data/lib/y_support/core_ext/numeric.rb +2 -2
- data/lib/y_support/core_ext/object/inspection.rb +8 -2
- data/lib/y_support/core_ext/object.rb +3 -3
- data/lib/y_support/core_ext/string/misc.rb +9 -12
- data/lib/y_support/core_ext/string.rb +2 -2
- data/lib/y_support/core_ext/symbol.rb +2 -2
- data/lib/y_support/core_ext.rb +1 -1
- data/lib/y_support/flex_coerce/class_methods.rb +49 -0
- data/lib/y_support/flex_coerce/flex_proxy.rb +121 -0
- data/lib/y_support/flex_coerce/module_methods.rb +37 -0
- data/lib/y_support/flex_coerce.rb +24 -0
- data/lib/y_support/kde.rb +1 -1
- data/lib/y_support/literate.rb +253 -0
- data/lib/y_support/local_object.rb +1 -1
- data/lib/y_support/name_magic/array_methods.rb +48 -0
- data/lib/y_support/name_magic/class_methods.rb +205 -161
- data/lib/y_support/name_magic/hash_methods.rb +33 -0
- data/lib/y_support/name_magic/namespace.rb +449 -0
- data/lib/y_support/name_magic.rb +358 -100
- data/lib/y_support/null_object.rb +1 -1
- data/lib/y_support/respond_to.rb +1 -1
- data/lib/y_support/stdlib_ext/matrix/misc.rb +2 -2
- data/lib/y_support/stdlib_ext/matrix.rb +2 -2
- data/lib/y_support/stdlib_ext.rb +1 -1
- data/lib/y_support/typing/array.rb +1 -1
- data/lib/y_support/typing/enumerable.rb +1 -1
- data/lib/y_support/typing/hash.rb +1 -1
- data/lib/y_support/typing/module.rb +1 -1
- data/lib/y_support/typing/object/typing.rb +17 -15
- data/lib/y_support/typing/object.rb +1 -1
- data/lib/y_support/typing.rb +14 -10
- data/lib/y_support/unicode.rb +1 -1
- data/lib/y_support/version.rb +1 -1
- data/lib/y_support/x.rb +2 -1
- data/test/flex_coerce_test.rb +134 -0
- data/test/literate_test.rb +231 -0
- data/test/misc_test.rb +49 -27
- data/test/name_magic_test.rb +907 -60
- data/test/typing_test.rb +7 -7
- metadata +14 -13
- data/lib/y_support/abstract_algebra.rb +0 -234
- data/lib/y_support/name_magic/array.rb +0 -38
- data/lib/y_support/name_magic/hash.rb +0 -31
- data/lib/y_support/name_magic/namespace_methods.rb +0 -260
- data/lib/y_support/try.rb +0 -133
- data/test/abstract_algebra_test.rb +0 -138
- data/test/performance_test_example.rb +0 -23
- 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=
|
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=
|
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=
|
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=
|
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=
|
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=
|
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.
|
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=
|
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.
|
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=
|
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=
|
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=
|
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=
|
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
|
-
|
1
|
+
require_relative 'object/typing'
|
data/lib/y_support/typing.rb
CHANGED
@@ -1,21 +1,25 @@
|
|
1
1
|
# encoding: utf-8
|
2
2
|
|
3
|
-
|
3
|
+
require_relative '../y_support'
|
4
4
|
|
5
5
|
# Typing library.
|
6
6
|
#
|
7
|
-
#
|
8
|
-
#
|
9
|
-
# and
|
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
|
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 |
|
17
|
-
Dir["#{File.dirname( __FILE__ )}/#{
|
18
|
-
dir = File.dirname( path ).match( "y_support/#{
|
19
|
-
|
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
|
data/lib/y_support/unicode.rb
CHANGED
data/lib/y_support/version.rb
CHANGED
data/lib/y_support/x.rb
CHANGED
@@ -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
|
-
|
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
|
-
|
178
|
-
end
|
179
|
-
|
180
|
-
it "should have #with_keys and #
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
|
190
|
-
|
191
|
-
|
192
|
-
|
193
|
-
|
194
|
-
|
195
|
-
|
196
|
-
|
197
|
-
|
198
|
-
|
199
|
-
|
200
|
-
|
201
|
-
|
202
|
-
|
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
|