ruby_ext 0.5.9 → 0.5.10
Sign up to get free protection for your applications and to get access to all the features.
- data/Rakefile +2 -3
- data/lib/rake_ext/project.rb +1 -2
- data/lib/rspec_ext.rb +37 -35
- data/lib/rspec_ext/nokogiri.rb +26 -0
- data/lib/ruby_ext/core.rb +3 -5
- data/lib/ruby_ext/core/array.rb +1 -1
- data/lib/ruby_ext/core/basic_object.rb +1 -1
- data/lib/ruby_ext/core/deep_clone.rb +3 -10
- data/lib/ruby_ext/core/enumerable.rb +3 -3
- data/lib/ruby_ext/core/false_class.rb +1 -1
- data/lib/ruby_ext/core/hash.rb +23 -7
- data/lib/ruby_ext/core/module.rb +37 -57
- data/lib/ruby_ext/core/multiple_inheritance.rb +3 -3
- data/lib/ruby_ext/core/must.rb +0 -16
- data/lib/ruby_ext/core/nil_class.rb +5 -0
- data/lib/ruby_ext/core/object.rb +7 -7
- data/lib/ruby_ext/core/open_object.rb +7 -25
- data/lib/ruby_ext/core/string.rb +1 -6
- data/lib/ruby_ext/more.rb +2 -0
- data/lib/ruby_ext/more/callbacks.rb +37 -0
- data/lib/ruby_ext/more/declarative_cache.rb +45 -56
- data/lib/yaml_fix.rb +9 -0
- data/spec/core/array_spec.rb +1 -1
- data/spec/core/deep_clone_spec.rb +4 -2
- data/spec/core/enumerable.rb +1 -1
- data/spec/core/module_spec.rb +65 -107
- data/spec/core/multiple_inheritance_spec.rb +4 -4
- data/spec/core/must_spec.rb +1 -1
- data/spec/core/object_spec.rb +6 -6
- data/spec/core/open_object_spec.rb +1 -1
- data/spec/more/callbacks_spec.rb +90 -20
- data/spec/more/declarative_cache_spec.rb +96 -75
- data/spec/more/observable_spec.rb +10 -34
- data/spec/more/open_constructor_spec.rb +14 -11
- data/spec/spec_helper.rb +2 -0
- metadata +5 -6
- data/lib/rspec_ext/xhtml.rb +0 -48
- data/lib/ruby_ext/fixes.rb +0 -6
- data/spec/core/spec_helper.rb +0 -2
- data/spec/more/spec_helper.rb +0 -2
data/lib/ruby_ext/core/must.rb
CHANGED
@@ -40,14 +40,6 @@ class MustAssertions < BasicObject
|
|
40
40
|
end
|
41
41
|
alias_method :an, :a
|
42
42
|
|
43
|
-
# def be klass = nil
|
44
|
-
# if klass.class == Array
|
45
|
-
# klass.any?{|k| @obj.respond_to :is?, k}
|
46
|
-
# else
|
47
|
-
# @obj.respond_to :is?, klass
|
48
|
-
# end
|
49
|
-
# end
|
50
|
-
|
51
43
|
def include o
|
52
44
|
@obj.include? o
|
53
45
|
end
|
@@ -184,12 +176,4 @@ Object.class_eval do
|
|
184
176
|
def must_not_be
|
185
177
|
must_not.be
|
186
178
|
end
|
187
|
-
|
188
|
-
# def must_have
|
189
|
-
# must.have
|
190
|
-
# end
|
191
|
-
#
|
192
|
-
# def must_not_have
|
193
|
-
# must_not.have
|
194
|
-
# end
|
195
179
|
end
|
data/lib/ruby_ext/core/object.rb
CHANGED
@@ -9,13 +9,13 @@ Object.class_eval do
|
|
9
9
|
respond_to?(:empty?) ? empty? : !self
|
10
10
|
end
|
11
11
|
|
12
|
-
def metaclass &block
|
13
|
-
|
14
|
-
end
|
15
|
-
def metaclass_eval &block
|
16
|
-
|
17
|
-
|
18
|
-
end
|
12
|
+
# def metaclass &block
|
13
|
+
# (class << self; self; end)
|
14
|
+
# end
|
15
|
+
# def metaclass_eval &block
|
16
|
+
# metaclass.class_eval(&block)
|
17
|
+
# self
|
18
|
+
# end
|
19
19
|
|
20
20
|
def respond_to method, *args
|
21
21
|
respond_to?(method) ? send(method, *args) : nil
|
@@ -126,6 +126,13 @@ class OpenObject < Hash
|
|
126
126
|
# support :extract_options for OpenObject (Rails integration)
|
127
127
|
def extractable_options?; true end
|
128
128
|
|
129
|
+
def deep_clone
|
130
|
+
clone = super
|
131
|
+
clone.clear
|
132
|
+
each{|k, v| clone[k.deep_clone] = v.deep_clone}
|
133
|
+
clone
|
134
|
+
end
|
135
|
+
|
129
136
|
protected
|
130
137
|
def method_missing m, arg = nil, &block
|
131
138
|
type = m[-1,1]
|
@@ -140,29 +147,4 @@ class OpenObject < Hash
|
|
140
147
|
self[m]
|
141
148
|
end
|
142
149
|
end
|
143
|
-
end
|
144
|
-
|
145
|
-
|
146
|
-
#
|
147
|
-
# Core Extensions
|
148
|
-
#
|
149
|
-
class NilClass
|
150
|
-
def to_openobject deep = false
|
151
|
-
OpenObject.new
|
152
|
-
end
|
153
|
-
alias_method :to_oo, :to_openobject
|
154
|
-
end
|
155
|
-
|
156
|
-
class Hash
|
157
|
-
def to_openobject deep = false
|
158
|
-
OpenObject.initialize_from self, deep
|
159
|
-
end
|
160
|
-
alias_method :to_oo, :to_openobject
|
161
|
-
|
162
|
-
alias_method :oo_eql, :==
|
163
|
-
def == other
|
164
|
-
true if self.equal? other
|
165
|
-
other == self if other.is_a? OpenObject
|
166
|
-
oo_eql other
|
167
|
-
end
|
168
150
|
end
|
data/lib/ruby_ext/core/string.rb
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
String
|
1
|
+
class String
|
2
2
|
def indent spaces = 2
|
3
3
|
indent = ' ' * spaces
|
4
4
|
gsub /^/, indent
|
@@ -20,11 +20,6 @@ String.class_eval do
|
|
20
20
|
[self]
|
21
21
|
end
|
22
22
|
|
23
|
-
def self.secure_token
|
24
|
-
original = [Time.now, (1..10).map{ rand.to_s }]
|
25
|
-
Digest::SHA1.hexdigest(original.flatten.join('--'))
|
26
|
-
end
|
27
|
-
|
28
23
|
def underscore
|
29
24
|
word = self.dup
|
30
25
|
word.gsub!(/::/, '/')
|
data/lib/ruby_ext/more.rb
CHANGED
@@ -176,6 +176,22 @@ module RubyExt::Callbacks
|
|
176
176
|
end
|
177
177
|
end
|
178
178
|
|
179
|
+
# We need to prevent callback from rinning multiple times if nested
|
180
|
+
# (need this for wrapping methods with callbacks to correctly call super).
|
181
|
+
def run_callbacks_only_once callback_name, data = {}, &block
|
182
|
+
set = Thread.current[callback_name] ||= {}
|
183
|
+
if set.include? object_id
|
184
|
+
block.call if block
|
185
|
+
else
|
186
|
+
begin
|
187
|
+
set[object_id] = true
|
188
|
+
run_callbacks callback_name, data, &block
|
189
|
+
ensure
|
190
|
+
set.delete object_id
|
191
|
+
end
|
192
|
+
end
|
193
|
+
end
|
194
|
+
|
179
195
|
module ClassMethods
|
180
196
|
inheritable_accessor :callbacks, {}
|
181
197
|
|
@@ -206,5 +222,26 @@ module RubyExt::Callbacks
|
|
206
222
|
(self.callbacks[callback_name] ||= []) << callback
|
207
223
|
end
|
208
224
|
|
225
|
+
def wrap_method_with_callbacks method, callback
|
226
|
+
method_without_callback = :"#{method}_without_#{callback}_of_#{self.alias}"
|
227
|
+
if method_defined? method_without_callback
|
228
|
+
raise "can't wrap method #{method} with #{callback} of #{self.alias} twice!"
|
229
|
+
end
|
230
|
+
|
231
|
+
alias_method method_without_callback, method
|
232
|
+
define_method method do |*args, &block|
|
233
|
+
# We can't use run_callbacks, because in case of the `super`
|
234
|
+
# call it will be runned twice.
|
235
|
+
run_callbacks_only_once callback do
|
236
|
+
send method_without_callback, *args, &block
|
237
|
+
end
|
238
|
+
end
|
239
|
+
end
|
240
|
+
|
241
|
+
def wrap_with_callback callback
|
242
|
+
instance_methods(false).each do |method|
|
243
|
+
wrap_method_with_callbacks method, callback
|
244
|
+
end
|
245
|
+
end
|
209
246
|
end
|
210
247
|
end
|
@@ -1,78 +1,67 @@
|
|
1
|
-
require 'monitor'
|
2
|
-
|
3
1
|
module RubyExt::DeclarativeCache
|
4
|
-
|
2
|
+
class << self
|
5
3
|
|
6
|
-
|
7
|
-
|
8
|
-
|
4
|
+
def cache_method klass, *methods
|
5
|
+
methods.each do |method|
|
6
|
+
klass.class_eval do
|
7
|
+
escaped_method = escape_method method
|
8
|
+
method_with_cache = :"#{escaped_method}_with_cache"
|
9
|
+
method_without_cache = :"#{escaped_method}_without_cache"
|
10
|
+
iv_check = "@#{escaped_method}_cache_check"
|
11
|
+
iv = "@#{escaped_method}_cache"
|
9
12
|
|
10
|
-
|
11
|
-
methods.each do |method|
|
12
|
-
klass.class_eval do
|
13
|
-
escaped_method = escape_method(method)
|
14
|
-
method_with_cache, method_without_cache = "#{escaped_method}_with_cache".to_sym, "#{escaped_method}_without_cache".to_sym
|
15
|
-
iv_check = "@#{escaped_method}_cache_check"
|
16
|
-
iv = "@#{escaped_method}_cache"
|
13
|
+
alias_method method_without_cache, method
|
17
14
|
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
alias_method method_without_cache, method
|
15
|
+
define_method method_with_cache do |*args|
|
16
|
+
raise "You tried to use cache without params for method with \
|
17
|
+
params (use 'cache_method_with_params' instead)!" unless args.empty?
|
22
18
|
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
instance_variable_set iv, cached
|
29
|
-
instance_variable_set iv_check, true
|
30
|
-
end
|
31
|
-
end
|
32
|
-
cached
|
19
|
+
unless cached = instance_variable_get(iv)
|
20
|
+
unless check = instance_variable_get(iv_check)
|
21
|
+
cached = send method_without_cache
|
22
|
+
instance_variable_set iv, cached
|
23
|
+
instance_variable_set iv_check, true
|
33
24
|
end
|
34
|
-
|
35
|
-
alias_method method, method_with_cache
|
36
25
|
end
|
26
|
+
cached
|
37
27
|
end
|
28
|
+
|
29
|
+
alias_method method, method_with_cache
|
38
30
|
end
|
39
31
|
end
|
32
|
+
end
|
40
33
|
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
if instance_methods.include?(method_with_cache) or instance_methods.include?(method_without_cache)
|
50
|
-
warn "can't cache the :#{method} twice!"
|
51
|
-
else
|
52
|
-
alias_method method_without_cache, method
|
53
|
-
|
54
|
-
define_method method_with_cache do |*args|
|
55
|
-
unless results = instance_variable_get(iv)
|
56
|
-
results = Hash.new(NotDefined)
|
57
|
-
instance_variable_set iv, results
|
58
|
-
end
|
34
|
+
def cache_method_with_params klass, *methods
|
35
|
+
methods.each do |method|
|
36
|
+
klass.class_eval do
|
37
|
+
escaped_method = escape_method method
|
38
|
+
method_with_cache = :"#{escaped_method}_with_cache"
|
39
|
+
method_without_cache = :"#{escaped_method}_without_cache"
|
40
|
+
iv_check = "@#{escaped_method}_cache_check"
|
41
|
+
iv = "@#{escaped_method}_cache"
|
59
42
|
|
60
|
-
|
43
|
+
alias_method method_without_cache, method
|
61
44
|
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
45
|
+
define_method method_with_cache do |*args|
|
46
|
+
unless results = instance_variable_get(iv)
|
47
|
+
results = Hash.new(NotDefined)
|
48
|
+
instance_variable_set iv, results
|
49
|
+
end
|
66
50
|
|
67
|
-
|
68
|
-
end
|
51
|
+
result = results[args]
|
69
52
|
|
70
|
-
|
53
|
+
if result.equal? NotDefined
|
54
|
+
result = send method_without_cache, *args
|
55
|
+
results[args] = result
|
71
56
|
end
|
57
|
+
|
58
|
+
result
|
72
59
|
end
|
60
|
+
|
61
|
+
alias_method method, method_with_cache
|
73
62
|
end
|
74
63
|
end
|
75
|
-
|
76
64
|
end
|
65
|
+
|
77
66
|
end
|
78
67
|
end
|
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/spec/core/array_spec.rb
CHANGED
@@ -1,6 +1,8 @@
|
|
1
|
-
require "
|
1
|
+
require "spec_helper"
|
2
2
|
|
3
3
|
describe 'deep_clone' do
|
4
|
+
after{remove_constants :Metadata}
|
5
|
+
|
4
6
|
it "basic" do
|
5
7
|
hash, array = {}, ['value']
|
6
8
|
hash['key'] = array
|
@@ -15,7 +17,7 @@ describe 'deep_clone' do
|
|
15
17
|
array2.object_id.should_not == array.object_id
|
16
18
|
end
|
17
19
|
|
18
|
-
it do
|
20
|
+
it 'cloning object tree' do
|
19
21
|
class Metadata
|
20
22
|
attr_accessor :registry
|
21
23
|
|
data/spec/core/enumerable.rb
CHANGED
data/spec/core/module_spec.rb
CHANGED
@@ -1,151 +1,109 @@
|
|
1
|
-
require "
|
1
|
+
require "spec_helper"
|
2
2
|
|
3
3
|
describe "Module" do
|
4
|
-
after
|
5
|
-
remove_constants %w(
|
6
|
-
A X Y Z
|
7
|
-
InheritableAccessorForModule
|
8
|
-
InheritableAccessorForClass
|
9
|
-
InheritableAccessor
|
10
|
-
InheritableAccessorBase
|
11
|
-
InheritableAccessorA
|
12
|
-
InheritableAccessorB
|
13
|
-
)
|
14
|
-
end
|
4
|
+
after{remove_constants :A, :B, :C, :ABase}
|
15
5
|
|
16
|
-
it "
|
6
|
+
it "namespace" do
|
17
7
|
class A
|
18
8
|
class B
|
19
|
-
class C
|
20
|
-
|
21
|
-
end
|
9
|
+
class C; end
|
22
10
|
end
|
23
11
|
end
|
24
12
|
|
25
|
-
|
13
|
+
A.namespace.should == nil
|
26
14
|
A::B::C.namespace.should == A::B
|
27
15
|
end
|
28
16
|
|
29
|
-
|
30
|
-
# class << self
|
31
|
-
# def anonymous_name
|
32
|
-
# self.name
|
33
|
-
# end
|
34
|
-
# end
|
35
|
-
# end
|
36
|
-
|
37
|
-
it "name" do
|
17
|
+
it "alias" do
|
38
18
|
class A
|
39
19
|
class B
|
40
|
-
class C
|
41
|
-
|
42
|
-
end
|
20
|
+
class C; end
|
43
21
|
end
|
44
22
|
end
|
45
23
|
|
24
|
+
A::B::C.alias.should == 'C'
|
46
25
|
A::B::C.name.should == "A::B::C"
|
47
26
|
end
|
48
27
|
|
49
|
-
it "
|
50
|
-
|
51
|
-
class Y < X; end
|
52
|
-
class Z < Y; end
|
53
|
-
|
54
|
-
list = []
|
55
|
-
Z.each_ancestor{|a| list << a}
|
56
|
-
list.should include Y
|
57
|
-
list.should include X
|
58
|
-
list.should_not include Z
|
59
|
-
list.should_not include Object
|
60
|
-
list.should_not include Kernel
|
61
|
-
|
62
|
-
list = []
|
63
|
-
Z.each_ancestor(true){|a| list << a}
|
64
|
-
list.should include Y
|
65
|
-
list.should include X
|
66
|
-
list.should_not include Z
|
67
|
-
list.should include Object
|
68
|
-
list.should include Kernel
|
28
|
+
it "is?" do
|
29
|
+
Fixnum.is?(Numeric).should be_true
|
69
30
|
end
|
70
31
|
|
71
|
-
it "
|
72
|
-
|
73
|
-
|
74
|
-
class C
|
32
|
+
it "escape_method" do
|
33
|
+
Module.escape_method(:">_<_=_?").should == :gt_lt_assign_qst
|
34
|
+
end
|
75
35
|
|
36
|
+
describe "inheritable_accessor" do
|
37
|
+
it "module" do
|
38
|
+
module A
|
39
|
+
module ClassMethods
|
40
|
+
inheritable_accessor :callbacks, [:a]
|
41
|
+
inheritable_accessor :layout, 'a'
|
76
42
|
end
|
77
43
|
end
|
78
|
-
end
|
79
|
-
|
80
|
-
list = []
|
81
|
-
A::B::C.each_namespace{|n| list << n}
|
82
|
-
list.should == [A::B, A]
|
83
|
-
end
|
84
44
|
|
85
|
-
|
86
|
-
|
87
|
-
|
45
|
+
class B
|
46
|
+
inherit A
|
47
|
+
callbacks << :b
|
48
|
+
self.layout = 'b'
|
49
|
+
end
|
88
50
|
|
89
|
-
|
90
|
-
|
91
|
-
10*value
|
51
|
+
B.callbacks.should == [:a, :b]
|
52
|
+
B.layout.should == 'b'
|
92
53
|
end
|
93
|
-
end
|
94
|
-
|
95
|
-
it "escape_method" do
|
96
|
-
Object.escape_method("><=?")
|
97
|
-
end
|
98
54
|
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
55
|
+
it "class" do
|
56
|
+
class A
|
57
|
+
class << self
|
58
|
+
inheritable_accessor :callbacks, [:a]
|
59
|
+
inheritable_accessor :layout, 'a'
|
60
|
+
end
|
61
|
+
callbacks << :a2
|
104
62
|
end
|
105
|
-
end
|
106
63
|
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
inheritable_accessor :layout2, "for_class"
|
64
|
+
class B < A
|
65
|
+
callbacks << :b
|
66
|
+
self.layout = 'b'
|
111
67
|
end
|
112
|
-
callbacks2 << :set_user
|
113
|
-
end
|
114
68
|
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
69
|
+
A.callbacks.should == [:a, :a2]
|
70
|
+
B.callbacks.should == [:a, :a2, :b]
|
71
|
+
|
72
|
+
A.layout.should == 'a'
|
73
|
+
B.layout.should == 'b'
|
120
74
|
end
|
121
75
|
|
122
|
-
|
123
|
-
|
124
|
-
|
76
|
+
it "should correcly clone attributes (from error)" do
|
77
|
+
module ABase
|
78
|
+
module ClassMethods
|
79
|
+
inheritable_accessor :callbacks, []
|
80
|
+
end
|
81
|
+
end
|
125
82
|
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
83
|
+
class A
|
84
|
+
inherit ABase
|
85
|
+
callbacks << :a
|
86
|
+
end
|
130
87
|
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
inheritable_accessor :callbacks, []
|
88
|
+
class B
|
89
|
+
inherit ABase
|
90
|
+
callbacks << :b
|
135
91
|
end
|
136
|
-
end
|
137
92
|
|
138
|
-
|
139
|
-
|
140
|
-
callbacks << :a
|
93
|
+
A.callbacks.should == [:a]
|
94
|
+
B.callbacks.should == [:b]
|
141
95
|
end
|
96
|
+
end
|
142
97
|
|
143
|
-
|
144
|
-
|
145
|
-
|
98
|
+
it "delegate" do
|
99
|
+
class A
|
100
|
+
attr_accessor :target
|
101
|
+
delegate :a, to: :target
|
146
102
|
end
|
147
103
|
|
148
|
-
|
149
|
-
|
104
|
+
a = A.new
|
105
|
+
a.target = stub
|
106
|
+
a.target.should_receive(:a).with(:b)
|
107
|
+
a.a :b
|
150
108
|
end
|
151
109
|
end
|