y_support 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +20 -0
- data/Gemfile +4 -0
- data/LICENSE +22 -0
- data/README.md +29 -0
- data/Rakefile +2 -0
- data/lib/y_support/all.rb +40 -0
- data/lib/y_support/core_ext/array/misc.rb +45 -0
- data/lib/y_support/core_ext/array.rb +1 -0
- data/lib/y_support/core_ext/enumerable/misc.rb +32 -0
- data/lib/y_support/core_ext/enumerable.rb +1 -0
- data/lib/y_support/core_ext/hash/misc.rb +90 -0
- data/lib/y_support/core_ext/hash.rb +1 -0
- data/lib/y_support/core_ext/module/misc.rb +43 -0
- data/lib/y_support/core_ext/module.rb +2 -0
- data/lib/y_support/core_ext/numeric/misc.rb +13 -0
- data/lib/y_support/core_ext/numeric.rb +1 -0
- data/lib/y_support/core_ext/object/misc.rb +31 -0
- data/lib/y_support/core_ext/object.rb +1 -0
- data/lib/y_support/core_ext/string/misc.rb +80 -0
- data/lib/y_support/core_ext/string.rb +1 -0
- data/lib/y_support/core_ext/symbol/misc.rb +19 -0
- data/lib/y_support/core_ext/symbol.rb +1 -0
- data/lib/y_support/core_ext.rb +5 -0
- data/lib/y_support/inert_recorder.rb +51 -0
- data/lib/y_support/local_object.rb +39 -0
- data/lib/y_support/misc.rb +28 -0
- data/lib/y_support/name_magic.rb +373 -0
- data/lib/y_support/null_object.rb +96 -0
- data/lib/y_support/respond_to.rb +32 -0
- data/lib/y_support/stdlib_ext/matrix/misc.rb +134 -0
- data/lib/y_support/stdlib_ext/matrix.rb +2 -0
- data/lib/y_support/stdlib_ext.rb +3 -0
- data/lib/y_support/typing/array/typing.rb +17 -0
- data/lib/y_support/typing/array.rb +1 -0
- data/lib/y_support/typing/enumerable/typing.rb +75 -0
- data/lib/y_support/typing/enumerable.rb +1 -0
- data/lib/y_support/typing/hash/typing.rb +76 -0
- data/lib/y_support/typing/hash.rb +1 -0
- data/lib/y_support/typing/module/typing.rb +42 -0
- data/lib/y_support/typing/module.rb +1 -0
- data/lib/y_support/typing/object/typing.rb +178 -0
- data/lib/y_support/typing/object.rb +1 -0
- data/lib/y_support/typing.rb +43 -0
- data/lib/y_support/unicode.rb +76 -0
- data/lib/y_support/version.rb +3 -0
- data/lib/y_support.rb +33 -0
- data/test/inert_recorder_test.rb +34 -0
- data/test/local_object_test.rb +37 -0
- data/test/misc_test/test_module/fixture_class.rb +8 -0
- data/test/misc_test.rb +289 -0
- data/test/name_magic_test.rb +57 -0
- data/test/null_object_test.rb +50 -0
- data/test/respond_to_test.rb +46 -0
- data/test/typing_test.rb +213 -0
- data/test/unicode_test.rb +39 -0
- data/y_support.gemspec +22 -0
- metadata +137 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 39372bbe12e6643f53e78e2b4fd8666477554a67
|
4
|
+
data.tar.gz: 9d1c8f648ab7369104ba1ca178fe6ca4abec4cf7
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 7e3457d0f805683af3c83018bb7174b161868f614a77b90e7ecc022937ec9b4768fbbfc904717b97beb71dbe0f96296cac46fe60f52db06f89c80c9afa5ce755
|
7
|
+
data.tar.gz: 8a57a47dcb40f4c286ffcdf3ad19c0ccd3cd6a58bb32f7d32861701c6907c4734db0eb6e72b6490afcf43e8c2797b0661fda1e7166ed15267736729d45fb06b8
|
data/.gitignore
ADDED
data/Gemfile
ADDED
data/LICENSE
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2012 boris
|
2
|
+
|
3
|
+
MIT License
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
6
|
+
a copy of this software and associated documentation files (the
|
7
|
+
"Software"), to deal in the Software without restriction, including
|
8
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
9
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
+
permit persons to whom the Software is furnished to do so, subject to
|
11
|
+
the following conditions:
|
12
|
+
|
13
|
+
The above copyright notice and this permission notice shall be
|
14
|
+
included in all copies or substantial portions of the Software.
|
15
|
+
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
19
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,29 @@
|
|
1
|
+
# YSupport
|
2
|
+
|
3
|
+
Common support library for Y* gems.
|
4
|
+
|
5
|
+
## Installation
|
6
|
+
|
7
|
+
Add this line to your application's Gemfile:
|
8
|
+
|
9
|
+
gem 'y_support'
|
10
|
+
|
11
|
+
And then execute:
|
12
|
+
|
13
|
+
$ bundle
|
14
|
+
|
15
|
+
Or install it yourself as:
|
16
|
+
|
17
|
+
$ gem install y_support
|
18
|
+
|
19
|
+
## Usage
|
20
|
+
|
21
|
+
Require 'y_support/all', or require 'y_support/something', and use it.
|
22
|
+
|
23
|
+
## Contributing
|
24
|
+
|
25
|
+
1. Fork it
|
26
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
27
|
+
3. Commit your changes (`git commit -am 'Added some feature'`)
|
28
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
29
|
+
5. Create new Pull Request
|
data/Rakefile
ADDED
@@ -0,0 +1,40 @@
|
|
1
|
+
#encoding: utf-8
|
2
|
+
|
3
|
+
require 'y_support'
|
4
|
+
require 'y_support/name_magic'
|
5
|
+
require 'y_support/typing'
|
6
|
+
require 'y_support/unicode'
|
7
|
+
require 'y_support/respond_to'
|
8
|
+
require 'y_support/null_object'
|
9
|
+
require 'y_support/inert_recorder'
|
10
|
+
require 'y_support/local_object'
|
11
|
+
require 'y_support/misc'
|
12
|
+
|
13
|
+
|
14
|
+
# # Test me!
|
15
|
+
# class BlankSlate
|
16
|
+
# class << self
|
17
|
+
# # Hide the method named +name+ in the BlankSlate class. Don't
|
18
|
+
# # hide +instance_eval+ or any method beginning with "__".
|
19
|
+
# def hide( name )
|
20
|
+
# if instance_methods.include? name and
|
21
|
+
# name !~ /^(__|instance_eval)/
|
22
|
+
# @hidden_methods ||= {}
|
23
|
+
# @hidden_methods[name] = instance_method name
|
24
|
+
# undef_method name
|
25
|
+
# end
|
26
|
+
# end
|
27
|
+
|
28
|
+
# def find_hidden_method name
|
29
|
+
# @hidden_methods ||= {}
|
30
|
+
# @hidden_methods[name] || superclass.find_hidden_method( name )
|
31
|
+
# end
|
32
|
+
|
33
|
+
# # Redefine a previously hidden method
|
34
|
+
# def reveal name
|
35
|
+
# unbound_method = find_hidden_method name
|
36
|
+
# fail "Don't know how to reveal method '#{name}'" unless unbound_method
|
37
|
+
# define_method( name, unbound_method )
|
38
|
+
# end
|
39
|
+
# end
|
40
|
+
# end # class BlankSlate
|
@@ -0,0 +1,45 @@
|
|
1
|
+
class Array
|
2
|
+
# Converts an array, whose elements are also arrays, to a hash. Head
|
3
|
+
# (position 0) of each array is made to point at the rest of the array
|
4
|
+
# (tail), normally starting immediately after the head (position 1). The
|
5
|
+
# starting position of the tail can be controlled by an optional
|
6
|
+
# argument. Tails of 2 and more elements are represented as arrays.
|
7
|
+
#
|
8
|
+
def to_hash( tail_from = 1 )
|
9
|
+
self.reject { | e | e[0].nil? }.reduce({}) { |a, e|
|
10
|
+
tail = e[tail_from..-1]
|
11
|
+
a.merge( { e[0] => tail.size >= 2 ? tail : tail[0] } )
|
12
|
+
}
|
13
|
+
end
|
14
|
+
|
15
|
+
# Does things for each consecutive pair (expects a binary block).
|
16
|
+
#
|
17
|
+
def each_consecutive_pair
|
18
|
+
if block_given?
|
19
|
+
return self if ( n = self.size - 1 ) <= 0
|
20
|
+
n.times.with_index{|i| yield( self[i], self[i+1] ) }
|
21
|
+
return self
|
22
|
+
else
|
23
|
+
return Enumerator.new do |yielder|
|
24
|
+
n.times.with_index{|i| yielder << [ self[i], self[i+1] ] } unless
|
25
|
+
( n = self.size - 1 ) <= 0
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
# Allows style &[ function, *arguments ]
|
31
|
+
#
|
32
|
+
def to_proc
|
33
|
+
proc { |receiver| receiver.send *self }
|
34
|
+
end # def to_proc
|
35
|
+
|
36
|
+
# TEST ME
|
37
|
+
# def pretty_inspect
|
38
|
+
# each_slice( 4 ) { |slice|
|
39
|
+
# slice.map { |e|
|
40
|
+
# str = e.to_s[0..25]
|
41
|
+
# str + ' ' * ( 30 - str.size )
|
42
|
+
# }.reduce( :+ ) + "\n"
|
43
|
+
# }.reduce( :+ )
|
44
|
+
# end
|
45
|
+
end
|
@@ -0,0 +1 @@
|
|
1
|
+
require 'y_support/core_ext/array/misc'
|
@@ -0,0 +1,32 @@
|
|
1
|
+
#encoding: utf-8
|
2
|
+
|
3
|
+
module Enumerable
|
4
|
+
# Checks whether #all? collection elements are #kind_of? module
|
5
|
+
# supplied as an argument
|
6
|
+
#
|
7
|
+
def all_kind_of?( kind )
|
8
|
+
all? {|e| e.kind_of? kind }
|
9
|
+
end
|
10
|
+
|
11
|
+
# Checks whether #all? collection elements are #kind_of? Numeric.
|
12
|
+
#
|
13
|
+
def all_numeric?
|
14
|
+
all? {|e| e.kind_of? Numeric }
|
15
|
+
end
|
16
|
+
|
17
|
+
# Checks whether the receiver collection is fully included in the
|
18
|
+
# collection supplied as an argument.
|
19
|
+
#
|
20
|
+
def subset_of?( other_collection )
|
21
|
+
all? {|e| other_collection.include? e }
|
22
|
+
end
|
23
|
+
alias :⊂? :subset_of?
|
24
|
+
|
25
|
+
# Checks whether the receiver collection contains every element of
|
26
|
+
# the collection supplied as an argument.
|
27
|
+
#
|
28
|
+
def superset_of?( other_collection )
|
29
|
+
other.all? {|e| self.include? e }
|
30
|
+
end
|
31
|
+
alias :⊃? :superset_of?
|
32
|
+
end
|
@@ -0,0 +1 @@
|
|
1
|
+
require 'y_support/core_ext/enumerable/misc'
|
@@ -0,0 +1,90 @@
|
|
1
|
+
#encoding: utf-8
|
2
|
+
|
3
|
+
require 'active_support/core_ext/hash/reverse_merge'
|
4
|
+
|
5
|
+
class Hash
|
6
|
+
# reversed merge!: defaults.merge( self! )
|
7
|
+
alias :default! :reverse_merge!
|
8
|
+
|
9
|
+
# Applies a block as a mapping on all keys, returning a new hash
|
10
|
+
def with_keys
|
11
|
+
keys.each_with_object self.class.new do |hash_key, ꜧ|
|
12
|
+
ꜧ[ yield( hash_key ) ] = self[ hash_key ]
|
13
|
+
end
|
14
|
+
end
|
15
|
+
alias :do_with_keys :with_keys
|
16
|
+
|
17
|
+
# The difference from do_with_keys is that modify_keys expects block
|
18
|
+
# that takes 2 arguments (key: value pair) and returns the new key.
|
19
|
+
def modify_keys
|
20
|
+
each_with_object self.class.new do |hash_pair, ꜧ|
|
21
|
+
ꜧ[ yield( hash_pair ) ] = self[ hash_pair[0] ]
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
# Applies a block as a mapping on all values, returning a new hash
|
26
|
+
def with_values
|
27
|
+
each_with_object self.class.new do |hash_pair, ꜧ|
|
28
|
+
ꜧ[ hash_pair[0] ] = yield( hash_pair[1] )
|
29
|
+
end
|
30
|
+
end
|
31
|
+
alias :do_with_values :with_values
|
32
|
+
|
33
|
+
# Like #do_with_values, but modifies the receiver.
|
34
|
+
def with_values!
|
35
|
+
each_with_object self do |hash_pair, ꜧ|
|
36
|
+
hash_key, hash_val = hash_pair
|
37
|
+
ꜧ[ hash_key ] = yield( hash_val )
|
38
|
+
end
|
39
|
+
end
|
40
|
+
alias :do_with_values! :with_values!
|
41
|
+
|
42
|
+
# The difference from #do_with_values is that modify_values expects block
|
43
|
+
# that takes 2 arguments (key: value pair) and returns the new value.
|
44
|
+
def modify_values
|
45
|
+
each_with_object self.class.new do |hash_pair, ꜧ|
|
46
|
+
ꜧ[ hash_pair[0] ] = yield( hash_pair )
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
# Like #modify_values, but modifies the receiver
|
51
|
+
def modify_values!
|
52
|
+
each_with_object self do |hash_pair, ꜧ|
|
53
|
+
ꜧ[ hash_pair[0] ] = yield( hash_pair )
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
# Like #map that returns a hash.
|
58
|
+
def modify
|
59
|
+
each_with_object self.class.new do |hash_pair, ꜧ|
|
60
|
+
key, val = yield hash_pair
|
61
|
+
ꜧ[key] = val
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
# Makes hash keys accessible as methods. If the hash keys collide with
|
66
|
+
# its methods, ArgumentError is raised, unless :overwrite_methods
|
67
|
+
# option == true.
|
68
|
+
#
|
69
|
+
def dot!( oo = {} )
|
70
|
+
keys.each do |key|
|
71
|
+
msg = "key #{key} of #dot!-ted hash is not convertible to a symbol"
|
72
|
+
raise ArgumentError, msg unless key.respond_to? :to_sym
|
73
|
+
unless oo[:overwrite_methods]
|
74
|
+
if methods.include? key.to_sym
|
75
|
+
raise ArgumentError, "#dot!-ted hash must not have key names " +
|
76
|
+
"colliding with its methods"
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
define_singleton_method key.to_sym do
|
81
|
+
self[key]
|
82
|
+
end
|
83
|
+
|
84
|
+
define_singleton_method "#{key}=".to_sym do |value|
|
85
|
+
self[key] = value
|
86
|
+
end
|
87
|
+
end
|
88
|
+
return self
|
89
|
+
end
|
90
|
+
end
|
@@ -0,0 +1 @@
|
|
1
|
+
require 'y_support/core_ext/hash/misc'
|
@@ -0,0 +1,43 @@
|
|
1
|
+
#encoding: utf-8
|
2
|
+
|
3
|
+
class Module
|
4
|
+
# Further automation of soon-to-be-deprecated #autorequire.
|
5
|
+
#
|
6
|
+
def autoreq( *symbols, descending_path: '..', ascending_path_prefix: 'lib' )
|
7
|
+
|
8
|
+
require 'active_support/core_ext/string/inflections'
|
9
|
+
|
10
|
+
namespace = self.name
|
11
|
+
namespace_path = namespace.underscore
|
12
|
+
namespace_chain = namespace.split "::"
|
13
|
+
ascending_path = ascending_path_prefix + '/' + namespace_path
|
14
|
+
symbols.map( &:to_s ).each { |ς|
|
15
|
+
next if ς.strip.empty?
|
16
|
+
camelized_ß = ς.camelize.to_sym
|
17
|
+
path = './' + [ descending_path, ascending_path, ς ].join( '/' )
|
18
|
+
autoload camelized_ß, path
|
19
|
+
}
|
20
|
+
end
|
21
|
+
|
22
|
+
# I didn't write this method by myself.
|
23
|
+
#
|
24
|
+
def attr_accessor_with_default *symbols, &block
|
25
|
+
raise ArgumentError, 'Block with default value required!' unless block
|
26
|
+
symbols.each { |ß|
|
27
|
+
module_eval {
|
28
|
+
define_method "#{ß}=" do |arg|
|
29
|
+
instance_variable_set "@#{ß}", arg
|
30
|
+
end
|
31
|
+
define_method ß do
|
32
|
+
singleton_class.class_eval { attr_reader ß }
|
33
|
+
if instance_variables.include? "@#{ß}".to_sym then
|
34
|
+
instance_variable_get "@#{ß}"
|
35
|
+
else
|
36
|
+
instance_variable_set "@#{ß}", block.call
|
37
|
+
end
|
38
|
+
end
|
39
|
+
}
|
40
|
+
}
|
41
|
+
end
|
42
|
+
alias :attr_accessor_w_default :attr_accessor_with_default
|
43
|
+
end
|
@@ -0,0 +1 @@
|
|
1
|
+
require 'y_support/core_ext/numeric/misc'
|
@@ -0,0 +1,31 @@
|
|
1
|
+
# -*- coding: utf-8 -*-
|
2
|
+
|
3
|
+
class Object
|
4
|
+
def const_set_if_not_defined( const, value )
|
5
|
+
mod = self.is_a?(Module) ? self : self.singleton_class
|
6
|
+
mod.const_set( const, value ) unless mod.const_defined?( const )
|
7
|
+
end
|
8
|
+
|
9
|
+
def const_redefine_without_warning( const, value )
|
10
|
+
mod = self.is_a?(Module) ? self : self.singleton_class
|
11
|
+
mod.send(:remove_const, const) if mod.const_defined?( const )
|
12
|
+
mod.const_set( const, value )
|
13
|
+
end
|
14
|
+
|
15
|
+
# Create public attributes (ie. with readers) and initialize them with
|
16
|
+
# prescribed values. Takes a hash of { symbol => value } pairs. Existing methods
|
17
|
+
# are not overwritten by the new getters, unless option :overwrite_methods
|
18
|
+
# is set to true.
|
19
|
+
def singleton_set_attr_with_readers( hash, oo = {} )
|
20
|
+
hash.each { |key, val|
|
21
|
+
key = key.aE_respond_to( :to_sym, "key of the attr hash" ).to_sym
|
22
|
+
instance_variable_set( "@#{key}", val )
|
23
|
+
if oo[:overwrite_methods] then ⓒ.module_exec { attr_reader key }
|
24
|
+
elsif methods.include? key
|
25
|
+
raise "Attempt to add \##{key} getter failed: " +
|
26
|
+
"method \##{key} already defined."
|
27
|
+
else ⓒ.module_exec { attr_reader key } end
|
28
|
+
}
|
29
|
+
end
|
30
|
+
alias :ⓒ_set_attr_w_readers :singleton_set_attr_with_readers
|
31
|
+
end
|
@@ -0,0 +1 @@
|
|
1
|
+
require 'y_support/core_ext/object/misc'
|
@@ -0,0 +1,80 @@
|
|
1
|
+
#encoding: utf-8
|
2
|
+
|
3
|
+
require 'active_support/core_ext/object/blank'
|
4
|
+
|
5
|
+
class String
|
6
|
+
# Integer() style conversion, or false if conversion impossible.
|
7
|
+
#
|
8
|
+
def to_Integer
|
9
|
+
begin
|
10
|
+
int = Integer stripn
|
11
|
+
return int
|
12
|
+
rescue ArgumentError
|
13
|
+
return false
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
# Float() style conversion, or false if conversion impossible.
|
18
|
+
#
|
19
|
+
def to_Float
|
20
|
+
begin
|
21
|
+
fl = Float stripn
|
22
|
+
return fl
|
23
|
+
rescue ArgumentError
|
24
|
+
return false
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
# Like #strip, but also strips newlines.
|
29
|
+
#
|
30
|
+
def stripn
|
31
|
+
encode( universal_newline: true )
|
32
|
+
.gsub("\n", "")
|
33
|
+
.strip
|
34
|
+
end
|
35
|
+
|
36
|
+
# Joins a paragraph of possibly indented, newline separated lines into a
|
37
|
+
# single contiguous string.
|
38
|
+
#
|
39
|
+
def wring_heredoc
|
40
|
+
encode(universal_newline: true)
|
41
|
+
.split("\n") # split into lines
|
42
|
+
.map( &:strip ) # strip them
|
43
|
+
.delete_if( &:blank? ) # delete blank lines
|
44
|
+
.join " " # and join with whitspace
|
45
|
+
end
|
46
|
+
|
47
|
+
# If the string is empty, it gets replace with the string given as argument.
|
48
|
+
#
|
49
|
+
def default! default_string
|
50
|
+
strip.empty? ? clear << default_string.to_s : self
|
51
|
+
end
|
52
|
+
|
53
|
+
# As it says – replaces spaces with underscores.
|
54
|
+
#
|
55
|
+
def underscore_spaces
|
56
|
+
gsub ' ', '_'
|
57
|
+
end
|
58
|
+
|
59
|
+
# Converts a string into a standard symbol. While Symbol class objects can
|
60
|
+
# be created from any string, it is good practice to keep symbols free of
|
61
|
+
# whitespaces and weird characters, so that the are typed easily, usable as
|
62
|
+
# variable names etc. This method thus removes punctuation, removes
|
63
|
+
# superfluous spaces, and underscores the remaining ones, before returning
|
64
|
+
# the string.
|
65
|
+
#
|
66
|
+
def standardize
|
67
|
+
ς = self.dup
|
68
|
+
",.;".each_char { |c| ς.gsub! c, " " }
|
69
|
+
ς.stripn
|
70
|
+
.squeeze(" ")
|
71
|
+
.underscore_spaces
|
72
|
+
end
|
73
|
+
|
74
|
+
# Applies #standardize to the receiver and converts the result to a symbol.
|
75
|
+
#
|
76
|
+
def to_standardized_sym
|
77
|
+
standardize
|
78
|
+
.to_sym
|
79
|
+
end
|
80
|
+
end
|
@@ -0,0 +1 @@
|
|
1
|
+
require 'y_support/core_ext/string/misc'
|
@@ -0,0 +1,19 @@
|
|
1
|
+
# -*- coding: utf-8 -*-
|
2
|
+
class Symbol
|
3
|
+
# This method applies String#default! method to the receiver converted to
|
4
|
+
# a string. Of course, symbols are immutable, so in spite of the exclamation
|
5
|
+
# mark in the method name, a new symbol (supplied as argument) is returned,
|
6
|
+
# if the original one is considered "defaulted" (otherwise, original symbol
|
7
|
+
# is returned unchanged).
|
8
|
+
#
|
9
|
+
def default! default_symbol
|
10
|
+
to_s.default!( default_symbol ).to_sym
|
11
|
+
end
|
12
|
+
|
13
|
+
# Applies String#to_standardized_sym method to the recevier converted to a
|
14
|
+
# string.
|
15
|
+
#
|
16
|
+
def to_standardized_sym
|
17
|
+
to_s.to_standardized_sym
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1 @@
|
|
1
|
+
require 'y_support/core_ext/symbol/misc'
|
@@ -0,0 +1,51 @@
|
|
1
|
+
#encoding: utf-8
|
2
|
+
|
3
|
+
require 'y_support'
|
4
|
+
|
5
|
+
# Inert recorder is similar to a null object in the sense, that in response to
|
6
|
+
# almost all messages it returns self. But in addition, it records received
|
7
|
+
# messages along with their arguments and blocks (if given). Recoded messages
|
8
|
+
# are available via #recorded_messages reader, aliased #ρ (small Greek rho).
|
9
|
+
# Inert recorder does not require any arguments for initalization, but if they
|
10
|
+
# are supplied, they are silently recoded into @init_args (for arguments) and
|
11
|
+
# @init_block (for block, if given) instance variables, exposed via standard
|
12
|
+
# readers.
|
13
|
+
#
|
14
|
+
class InertRecorder
|
15
|
+
attr_reader :init_args, :init_block, :recorded_messages
|
16
|
+
alias ρ recorded_messages
|
17
|
+
|
18
|
+
# No arguments are required for initialization, but if they are supplied, they
|
19
|
+
# are silently recorded into @init_args (for argument array) and @init_block
|
20
|
+
# (for block, if given) instance variables, exposed via standard readers.
|
21
|
+
#
|
22
|
+
def initialize *args, &block
|
23
|
+
@init_args = args
|
24
|
+
@init_block = block
|
25
|
+
@recorded_messages = []
|
26
|
+
end
|
27
|
+
|
28
|
+
# Always true.
|
29
|
+
#
|
30
|
+
def present?; true end
|
31
|
+
|
32
|
+
# Always false.
|
33
|
+
#
|
34
|
+
def blank?; false end
|
35
|
+
|
36
|
+
# Always true.
|
37
|
+
#
|
38
|
+
def respond_to? ß, *args, █ true end
|
39
|
+
|
40
|
+
def method_missing ß, *args, &block # :nodoc:
|
41
|
+
@recorded_messages << [ ß, args, block ]
|
42
|
+
return self
|
43
|
+
end
|
44
|
+
end # class InertRecorder
|
45
|
+
|
46
|
+
|
47
|
+
class Object
|
48
|
+
# InertRecorder constructor.
|
49
|
+
#
|
50
|
+
def InertRecorder *args, █ InertRecorder.new *args, &block end
|
51
|
+
end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
#encoding: utf-8
|
2
|
+
|
3
|
+
require 'y_support'
|
4
|
+
|
5
|
+
# Object, whose business is to stay local to methods. Optional signature
|
6
|
+
# provides additional level of safety in ensuring object locality. (Signature
|
7
|
+
# accessor is :signature, aliased as :σ (small Greek sigma).)
|
8
|
+
#
|
9
|
+
class LocalObject
|
10
|
+
attr_reader :signature
|
11
|
+
alias σ signature
|
12
|
+
|
13
|
+
# Optional argument signature provides additional level of safety in
|
14
|
+
# ascertaining that the object indeed is of local origin.
|
15
|
+
#
|
16
|
+
def initialize signature=__callee__
|
17
|
+
@signature=signature
|
18
|
+
end
|
19
|
+
|
20
|
+
# True if the (optional) signature matches.
|
21
|
+
#
|
22
|
+
def local_object? signature=__callee__
|
23
|
+
signature == self.signature
|
24
|
+
end
|
25
|
+
alias ℓ? local_object?
|
26
|
+
end
|
27
|
+
|
28
|
+
|
29
|
+
class Object
|
30
|
+
# LocalObject constructor.
|
31
|
+
#
|
32
|
+
def LocalObject signature=nil; LocalObject.new signature end
|
33
|
+
alias L! LocalObject
|
34
|
+
|
35
|
+
# False for normal objects, overriden in the LocalObject class.
|
36
|
+
#
|
37
|
+
def local_object? signature=nil; false end
|
38
|
+
alias ℓ? local_object?
|
39
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
#encoding: utf-8
|
2
|
+
require 'y_support'
|
3
|
+
|
4
|
+
# Typing library.
|
5
|
+
#
|
6
|
+
# Apart from usual <em>typing by class and ancestry</em>, supported by built-in
|
7
|
+
# #kind_of?, alias #is_a? inquirerers, this typing library provides support for
|
8
|
+
# provides support for <em>typing by declaration</em> and <em>duck typing</em>.
|
9
|
+
#
|
10
|
+
# 1. Using method <b>declare_compliance</b>, a module can explicitly declare that
|
11
|
+
# it provides the interface compliant with another module. Corresponding inquirer
|
12
|
+
# methods are <b>declared_compliance</b> (returning a list of modules with which
|
13
|
+
# the receiver declares compliance or implicitly complies) and
|
14
|
+
# <b>declares_compliance?( other_module )</b>, which anwers whether the receiver
|
15
|
+
# complies with other_module. An object always implicitly complies with its class
|
16
|
+
# and class ancestry.
|
17
|
+
#
|
18
|
+
# 2. Duck type enforcement for method parameters is supported by a collection of
|
19
|
+
# enforcer methods (aka. run-time assertions). These methods look very much like
|
20
|
+
# assertions, but they start with <b>tE_...</b>, meaning "enforce by raising
|
21
|
+
# TypeError".
|
22
|
+
|
23
|
+
[ :core_ext, :stdlib_ext ].each do |ext|
|
24
|
+
Dir["#{File.dirname( __FILE__ )}/#{ext}/*/misc.rb"].sort.each { |path|
|
25
|
+
dir = File.dirname( path ).match( "y_support/#{ext}" ).post_match
|
26
|
+
require "y_support/#{ext}#{dir}/misc"
|
27
|
+
}
|
28
|
+
end
|