ruby_ext 0.4.11 → 0.4.12
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.
- data/Rakefile +6 -6
- data/lib/rake_ext.rb +10 -5
- data/lib/rake_ext/project.rb +31 -16
- data/lib/rspec_ext.rb +82 -19
- data/lib/ruby_ext.rb +1 -52
- data/lib/ruby_ext/core.rb +24 -0
- data/lib/ruby_ext/{array.rb → core/array.rb} +4 -2
- data/lib/ruby_ext/core/basic_object.rb +8 -0
- data/lib/ruby_ext/core/class.rb +0 -0
- data/lib/ruby_ext/{deep_clone.rb → core/deep_clone.rb} +3 -4
- data/lib/ruby_ext/core/enumerable.rb +17 -0
- data/lib/ruby_ext/{file.rb → core/file.rb} +5 -2
- data/lib/ruby_ext/core/hash.rb +23 -0
- data/lib/ruby_ext/{kernel.rb → core/kernel.rb} +0 -0
- data/lib/ruby_ext/{micelaneous.rb → core/micelaneous.rb} +0 -0
- data/lib/ruby_ext/{module.rb → core/module.rb} +13 -2
- data/lib/ruby_ext/{multiple_inheritance.rb → core/multiple_inheritance.rb} +30 -14
- data/lib/ruby_ext/{must.rb → core/must.rb} +30 -27
- data/lib/ruby_ext/{not_defined.rb → core/not_defined.rb} +0 -0
- data/lib/ruby_ext/{object.rb → core/object.rb} +0 -0
- data/lib/ruby_ext/{open_object.rb → core/open_object.rb} +21 -16
- data/lib/ruby_ext/{string.rb → core/string.rb} +27 -0
- data/lib/ruby_ext/{symbol.rb → core/symbol.rb} +0 -0
- data/lib/ruby_ext/fixes.rb +6 -0
- data/lib/ruby_ext/gems.rb +0 -1
- data/lib/ruby_ext/more.rb +11 -0
- data/lib/ruby_ext/more/declarative_cache.rb +96 -0
- data/lib/ruby_ext/more/micelaneous.rb +7 -0
- data/lib/ruby_ext/{observable2.rb → more/observable2.rb} +0 -0
- data/lib/ruby_ext/{open_constructor.rb → more/open_constructor.rb} +2 -2
- data/lib/ruby_ext/more/safe_hash.rb +214 -0
- data/lib/ruby_ext/{synchronize.rb → more/synchronize.rb} +5 -5
- data/lib/ruby_ext/{tuple.rb → more/tuple.rb} +0 -0
- data/lib/yaml_fix.rb +9 -0
- data/readme.md +46 -42
- data/spec/core/array_spec.rb +7 -0
- data/spec/{deep_clone_spec.rb → core/deep_clone_spec.rb} +2 -3
- data/spec/core/enumerable.rb +9 -0
- data/spec/{kernel_spec.rb → core/kernel_spec.rb} +4 -6
- data/spec/{kernel_spec → core/kernel_spec}/TheNamespace/ClassA.rb +0 -0
- data/spec/{kernel_spec → core/kernel_spec}/another_class.rb +0 -0
- data/spec/{kernel_spec → core/kernel_spec}/the_namespace/class_b.rb +0 -0
- data/spec/{module_spec.rb → core/module_spec.rb} +2 -4
- data/spec/{multiple_inheritance_spec.rb → core/multiple_inheritance_spec.rb} +28 -12
- data/spec/core/must_spec.rb +32 -0
- data/spec/{open_object_spec.rb → core/open_object_spec.rb} +6 -7
- data/spec/core/spec_helper.rb +2 -0
- data/spec/{declarative_cache_spec.rb → more/declarative_cache_spec.rb} +35 -8
- data/spec/{observable2_spec.rb → more/observable2_spec.rb} +3 -4
- data/spec/{open_constructor_spec.rb → more/open_constructor_spec.rb} +6 -7
- data/spec/more/safe_hash_spec.rb +133 -0
- data/spec/more/spec_helper.rb +2 -0
- data/spec/{synchronize_spec.rb → more/synchronize_spec.rb} +2 -3
- metadata +67 -100
- data/lib/ruby_ext/basic_object.rb +0 -22
- data/lib/ruby_ext/class.rb +0 -11
- data/lib/ruby_ext/declarative_cache.rb +0 -85
- data/lib/ruby_ext/extra_blank_slate.rb +0 -17
- data/lib/ruby_ext/hash.rb +0 -15
- data/lib/ruby_ext/prepare_arguments.rb +0 -105
- data/lib/ruby_ext/prototype_inheritance.rb +0 -110
- data/lib/ruby_ext/should.rb +0 -166
- data/lib/rubyopt.rb +0 -7
- data/spec/_prototype_inheritance_spec.rb +0 -190
- data/spec/array_spec.rb +0 -8
- data/spec/must_spec.rb +0 -29
- data/spec/prepare_arguments_spec.rb +0 -46
- data/spec/should_spec.rb +0 -24
- data/spec/spec_helper.rb +0 -19
data/lib/ruby_ext/gems.rb
CHANGED
@@ -1 +0,0 @@
|
|
1
|
-
gem 'facets', '2.9.0'
|
@@ -0,0 +1,96 @@
|
|
1
|
+
require 'monitor'
|
2
|
+
|
3
|
+
Module.class_eval do
|
4
|
+
def cache_method *methods
|
5
|
+
DeclarativeCache.cache_method self, *methods
|
6
|
+
end
|
7
|
+
|
8
|
+
def cache_method_with_params *methods
|
9
|
+
DeclarativeCache.cache_method_with_params self, *methods
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
class Object
|
14
|
+
def clear_cache
|
15
|
+
instance_variables.each do |iv|
|
16
|
+
remove_instance_variable iv if iv =~ /_cache$/ or iv =~ /_cache_check$/
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
module DeclarativeCache
|
22
|
+
DISABLED = false
|
23
|
+
|
24
|
+
warn "CASHE DISABLED" if DISABLED
|
25
|
+
unless DISABLED
|
26
|
+
class << self
|
27
|
+
|
28
|
+
def cache_method klass, *methods
|
29
|
+
methods.each do |method|
|
30
|
+
klass.class_eval do
|
31
|
+
escaped_method = escape_method(method)
|
32
|
+
method_with_cache, method_without_cache = "#{escaped_method}_with_cache".to_sym, "#{escaped_method}_without_cache".to_sym
|
33
|
+
iv_check = "@#{escaped_method}_cache_check"
|
34
|
+
iv = "@#{escaped_method}_cache"
|
35
|
+
|
36
|
+
if instance_methods.include?(method_with_cache) or instance_methods.include?(method_without_cache)
|
37
|
+
warn "can't cache the :#{method} twice!"
|
38
|
+
else
|
39
|
+
alias_method method_without_cache, method
|
40
|
+
|
41
|
+
define_method method_with_cache do |*args|
|
42
|
+
raise "You tried to use cache without params for method with params (use 'cache_method_with_params' instead)!" unless args.empty?
|
43
|
+
unless cached = instance_variable_get(iv)
|
44
|
+
unless check = instance_variable_get(iv_check)
|
45
|
+
cached = send method_without_cache
|
46
|
+
instance_variable_set iv, cached
|
47
|
+
instance_variable_set iv_check, true
|
48
|
+
end
|
49
|
+
end
|
50
|
+
cached
|
51
|
+
end
|
52
|
+
|
53
|
+
alias_method method, method_with_cache
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
def cache_method_with_params klass, *methods
|
60
|
+
methods.each do |method|
|
61
|
+
klass.class_eval do
|
62
|
+
escaped_method = escape_method(method)
|
63
|
+
method_with_cache, method_without_cache = "#{escaped_method}_with_cache".to_sym, "#{escaped_method}_without_cache".to_sym
|
64
|
+
iv_check = "@#{escaped_method}_cache_check"
|
65
|
+
iv = "@#{escaped_method}_cache"
|
66
|
+
|
67
|
+
if instance_methods.include?(method_with_cache) or instance_methods.include?(method_without_cache)
|
68
|
+
warn "can't cache the :#{method} twice!"
|
69
|
+
else
|
70
|
+
alias_method method_without_cache, method
|
71
|
+
|
72
|
+
define_method method_with_cache do |*args|
|
73
|
+
unless results = instance_variable_get(iv)
|
74
|
+
results = Hash.new(NotDefined)
|
75
|
+
instance_variable_set iv, results
|
76
|
+
end
|
77
|
+
|
78
|
+
result = results[args]
|
79
|
+
|
80
|
+
if result.equal? NotDefined
|
81
|
+
result = send method_without_cache, *args
|
82
|
+
results[args] = result
|
83
|
+
end
|
84
|
+
|
85
|
+
result
|
86
|
+
end
|
87
|
+
|
88
|
+
alias_method method, method_with_cache
|
89
|
+
end
|
90
|
+
end
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
end
|
95
|
+
end
|
96
|
+
end
|
File without changes
|
@@ -33,13 +33,13 @@ module OpenConstructor
|
|
33
33
|
return self
|
34
34
|
end
|
35
35
|
|
36
|
-
def
|
36
|
+
def set! values
|
37
37
|
values.each do |k, v|
|
38
38
|
self.send k.to_writer, v
|
39
39
|
end
|
40
40
|
return self
|
41
41
|
end
|
42
|
-
alias_method :set
|
42
|
+
# alias_method :set! #, :set_with_check
|
43
43
|
|
44
44
|
def to_hash
|
45
45
|
hash = {}
|
@@ -0,0 +1,214 @@
|
|
1
|
+
# require 'singleton'
|
2
|
+
|
3
|
+
class SafeHash < BasicObject
|
4
|
+
attr_reader :hash
|
5
|
+
|
6
|
+
alias_method :send, :__send__
|
7
|
+
|
8
|
+
def initialize hash = {}
|
9
|
+
reinitialize hash
|
10
|
+
end
|
11
|
+
|
12
|
+
def []= key, value
|
13
|
+
::SafeHash.forbidden! key
|
14
|
+
# value = ::SafeHash.new value if value.is_a? ::Hash
|
15
|
+
# @hash[key.to_sym] = value
|
16
|
+
end
|
17
|
+
|
18
|
+
def set! key, value
|
19
|
+
value = ::SafeHash.new value if value.is_a? ::Hash
|
20
|
+
@hash[key.to_sym] = value
|
21
|
+
end
|
22
|
+
def set *args; raise "you probably mistyped :set! method!" end
|
23
|
+
|
24
|
+
def include? key
|
25
|
+
@hash.include? key.to_sym
|
26
|
+
end
|
27
|
+
|
28
|
+
def tap &b
|
29
|
+
b.call self
|
30
|
+
self
|
31
|
+
end
|
32
|
+
|
33
|
+
def [] key, if_not_exist = ::NotDefined
|
34
|
+
last = key[-1]
|
35
|
+
if last == '!'
|
36
|
+
key = key[0..-2].to_sym
|
37
|
+
if @hash.include? key
|
38
|
+
@hash[key]
|
39
|
+
else
|
40
|
+
raise "no key :#{key}"
|
41
|
+
end
|
42
|
+
elsif last == '?'
|
43
|
+
key = key[0..-2].to_sym
|
44
|
+
@hash.include? key
|
45
|
+
else
|
46
|
+
key = key.to_sym
|
47
|
+
if @hash.include? key
|
48
|
+
@hash[key]
|
49
|
+
elsif if_not_exist == ::NotDefined
|
50
|
+
SafeNil.new key
|
51
|
+
else
|
52
|
+
return if_not_exist
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
def reinitialize hash
|
58
|
+
@hash = {}
|
59
|
+
merge! hash
|
60
|
+
# hash.each do |k, v|
|
61
|
+
# v = ::SafeHash.new v if v.is_a? ::Hash
|
62
|
+
# @hash[k.to_sym] = v
|
63
|
+
# end
|
64
|
+
# @hash.freeze
|
65
|
+
end
|
66
|
+
|
67
|
+
def method_missing m, obj = ::NotDefined, &b
|
68
|
+
raise "invalid usage, can't pass block to (:#{m})!" if b
|
69
|
+
last = m[-1]
|
70
|
+
if last == '='
|
71
|
+
::SafeHash.forbidden! m[0..-2]
|
72
|
+
# self[m[0..-2]] = obj
|
73
|
+
else
|
74
|
+
self[m, obj]
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
def to_yaml *args
|
79
|
+
@hash.to_yaml *args
|
80
|
+
end
|
81
|
+
|
82
|
+
def inspect
|
83
|
+
@hash.inspect
|
84
|
+
end
|
85
|
+
|
86
|
+
def delete key
|
87
|
+
@hash.delete key.to_sym
|
88
|
+
end
|
89
|
+
|
90
|
+
def merge! hash, options = {}
|
91
|
+
# parsing arguments
|
92
|
+
deep = options[:deep] || true
|
93
|
+
override = options[:override] || false
|
94
|
+
blank = options[:blank] || false
|
95
|
+
options.validate_options! :deep, :override, :blank
|
96
|
+
raise "invalid options, can't do both :blank and :override simultaneously!" if blank and override
|
97
|
+
|
98
|
+
# merging
|
99
|
+
hash.each do |k, v|
|
100
|
+
k = k.to_sym
|
101
|
+
if @hash.include? k
|
102
|
+
if deep and (old_v = @hash[k]).respond_to(:is_a_safe_hash?) and v.is_a?(::Hash)
|
103
|
+
old_v.merge! v, options
|
104
|
+
else
|
105
|
+
if blank
|
106
|
+
# do nothing
|
107
|
+
elsif override
|
108
|
+
self.set! k, v
|
109
|
+
else
|
110
|
+
raise "can't override :#{k} config value!" unless override
|
111
|
+
end
|
112
|
+
end
|
113
|
+
else
|
114
|
+
self.set! k, v
|
115
|
+
end
|
116
|
+
end
|
117
|
+
end
|
118
|
+
def merge *args; raise "you probably mistyped :merge! method!" end
|
119
|
+
|
120
|
+
def merge_if_blank! hash, options = {}
|
121
|
+
options[:blank] = true
|
122
|
+
merge! hash, options
|
123
|
+
end
|
124
|
+
def merge_if_blank *args; raise "you probably mistyped :merge_if_blank method!" end
|
125
|
+
|
126
|
+
# deep conversion, check and converts nested SafeHashes to Hashes
|
127
|
+
def to_hash options = {}
|
128
|
+
r = {}
|
129
|
+
@hash.each do |k, v|
|
130
|
+
k = k.to_s if options[:to_s]
|
131
|
+
r[k] = if v.respond_to :is_a_safe_hash?
|
132
|
+
v.to_hash options
|
133
|
+
else
|
134
|
+
v
|
135
|
+
end
|
136
|
+
end
|
137
|
+
r
|
138
|
+
end
|
139
|
+
alias_method :to_h, :to_hash
|
140
|
+
|
141
|
+
def is_a_safe_hash?
|
142
|
+
true
|
143
|
+
end
|
144
|
+
|
145
|
+
|
146
|
+
class SafeNil < BasicObject
|
147
|
+
# include ::Singleton
|
148
|
+
|
149
|
+
def initialize key
|
150
|
+
@key = key
|
151
|
+
end
|
152
|
+
|
153
|
+
def [] key, if_not_exist = ::NotDefined
|
154
|
+
last = key[-1]
|
155
|
+
if last == '!'
|
156
|
+
raise "no key :#{key}"
|
157
|
+
elsif last == '?'
|
158
|
+
false
|
159
|
+
elsif if_not_exist == ::NotDefined
|
160
|
+
SafeNil.new key
|
161
|
+
else
|
162
|
+
return if_not_exist
|
163
|
+
end
|
164
|
+
end
|
165
|
+
|
166
|
+
def method_missing m, if_not_exist = ::NotDefined, &b
|
167
|
+
raise "invalid usage, can't pass block to (:#{m})!" if b
|
168
|
+
last = m[-1]
|
169
|
+
if last == '='
|
170
|
+
::SafeHash.forbidden! m[0..-2]
|
171
|
+
# raise "No key '#{@key}'!"
|
172
|
+
else
|
173
|
+
self[m, if_not_exist]
|
174
|
+
end
|
175
|
+
end
|
176
|
+
|
177
|
+
def include? key
|
178
|
+
false
|
179
|
+
end
|
180
|
+
|
181
|
+
def to_b
|
182
|
+
false
|
183
|
+
end
|
184
|
+
|
185
|
+
def to_yaml *args
|
186
|
+
nil.to_yaml *args
|
187
|
+
end
|
188
|
+
|
189
|
+
def to_h
|
190
|
+
{}
|
191
|
+
end
|
192
|
+
|
193
|
+
def to_s
|
194
|
+
raise "can't convert SafeNil for key '#{@key}' to String!"
|
195
|
+
end
|
196
|
+
|
197
|
+
def inspect
|
198
|
+
nil.inspect
|
199
|
+
end
|
200
|
+
end
|
201
|
+
|
202
|
+
|
203
|
+
class << self
|
204
|
+
def forbidden! key
|
205
|
+
raise "direct modifications of SafeHash is forbidden, use :merge instead (you are trying to assign :#{key} value)!"
|
206
|
+
end
|
207
|
+
end
|
208
|
+
|
209
|
+
|
210
|
+
protected
|
211
|
+
def p *a
|
212
|
+
::Object.send :p, *a
|
213
|
+
end
|
214
|
+
end
|
@@ -1,13 +1,13 @@
|
|
1
1
|
require 'monitor'
|
2
2
|
|
3
|
-
|
3
|
+
Module.class_eval do
|
4
4
|
def synchronize_method *methods
|
5
5
|
methods.each do |method|
|
6
|
-
raise "
|
6
|
+
raise "can't synchronize system method #{method}" if method =~ /^__/
|
7
7
|
|
8
|
-
als = "sync_#{escape_method(method)}"
|
8
|
+
als = "sync_#{escape_method(method)}".to_sym
|
9
9
|
|
10
|
-
raise "
|
10
|
+
raise "can't synchronize the '#{method}' twice!" if instance_methods.include?(als)
|
11
11
|
|
12
12
|
alias_method als, method
|
13
13
|
script = "\
|
@@ -20,7 +20,7 @@ end"
|
|
20
20
|
end
|
21
21
|
|
22
22
|
def synchronize_all_methods include_super = false
|
23
|
-
methods = self.instance_methods(include_super).collect{|m| m
|
23
|
+
methods = self.instance_methods(include_super).collect{|m| m}
|
24
24
|
synchronize_method *methods
|
25
25
|
end
|
26
26
|
end
|
File without changes
|
data/lib/yaml_fix.rb
ADDED
@@ -0,0 +1,9 @@
|
|
1
|
+
require 'yaml'
|
2
|
+
|
3
|
+
begin
|
4
|
+
require 'psych'
|
5
|
+
YAML::ENGINE.yamler = 'psych'
|
6
|
+
rescue Exception
|
7
|
+
warn "can't load 'psych', the new YAML engine (probably the 'libyaml' is not installed), usng 'sych' a deprecated one, \
|
8
|
+
there may be some problems with encoding."
|
9
|
+
end
|
data/readme.md
CHANGED
@@ -1,55 +1,55 @@
|
|
1
1
|
# Ruby extensions
|
2
|
-
**
|
2
|
+
**ruby_ext** is a collection of various utility classes and standard library extensions for the Ruby language.
|
3
3
|
|
4
4
|
## must - assertion tool, kind of RSpec assertions in runtime code
|
5
5
|
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
6
|
+
1.must_be.in 1..2
|
7
|
+
"a".must_be.in 'a', 'b', 'c'
|
8
|
+
key.must_be.a String
|
9
|
+
value.must_not_be.nil
|
10
|
+
must_be.never_called
|
11
|
+
a.must_be == b
|
12
12
|
|
13
13
|
## inherit - combines include & extend in one
|
14
14
|
Do you remember this *def self.included(base) ... end* hack? You don't need it anymore.
|
15
15
|
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
16
|
+
module Feature
|
17
|
+
def cool_method; end
|
18
|
+
class_methods do
|
19
|
+
def cool_class_method; end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
class TheClass
|
24
|
+
inherit Feature
|
25
|
+
end
|
26
|
+
|
27
|
+
TheClass.new.cool_method
|
28
|
+
TheClass.cool_class_method
|
29
|
+
|
30
30
|
## cache_method & synchronize_method
|
31
31
|
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
32
|
+
def complex_calculation
|
33
|
+
2 * 2
|
34
|
+
end
|
35
|
+
cache_method :complex_calculation
|
36
36
|
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
37
|
+
def money_transfer amount
|
38
|
+
@from -= amount
|
39
|
+
@to += amount
|
40
|
+
end
|
41
|
+
synchronize_method :money_transfer
|
42
42
|
|
43
43
|
## OpenConstructor - adds mass assignment to any class
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
44
|
+
|
45
|
+
class TheClass
|
46
|
+
include OpenConstructor
|
47
|
+
attr_accessor :a, :b
|
48
|
+
end
|
49
49
|
|
50
|
-
|
51
|
-
|
52
|
-
|
50
|
+
o = TheClass.new.set a: 'a', b: 'b'
|
51
|
+
o.a => 'a'
|
52
|
+
o.to_hash => {a: 'a', b: 'b'}
|
53
53
|
|
54
54
|
## More
|
55
55
|
|
@@ -57,10 +57,14 @@ These are just a small part of all handy methods and extensions, for more detail
|
|
57
57
|
|
58
58
|
# Usage
|
59
59
|
|
60
|
-
|
61
|
-
|
62
|
-
|
60
|
+
$ sudo gem install ruby_ext
|
61
|
+
|
62
|
+
require 'ruby_ext'
|
63
63
|
|
64
|
-
Copyright (c)
|
64
|
+
Copyright (c) Alexey Petrushin [http://4ire.net](http://4ire.net), released under the MIT license.
|
65
|
+
|
66
|
+
# TODO
|
67
|
+
|
68
|
+
- config.development{} should raise 'invalid usage'
|
65
69
|
|
66
70
|
[ioc]: http://en.wikipedia.org/wiki/Inversion_of_control
|