ruby_ext 0.5.9 → 0.5.10
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 +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
|