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.
- 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
|