ruby_ext 0.4.6
Sign up to get free protection for your applications and to get access to all the features.
- data/Rakefile +64 -0
- data/lib/ruby_ext/array.rb +13 -0
- data/lib/ruby_ext/basic_object.rb +22 -0
- data/lib/ruby_ext/class.rb +11 -0
- data/lib/ruby_ext/declarative_cache.rb +85 -0
- data/lib/ruby_ext/deep_clone.rb +62 -0
- data/lib/ruby_ext/extra_blank_slate.rb +16 -0
- data/lib/ruby_ext/file.rb +20 -0
- data/lib/ruby_ext/hash.rb +15 -0
- data/lib/ruby_ext/kernel.rb +69 -0
- data/lib/ruby_ext/micelaneous.rb +14 -0
- data/lib/ruby_ext/module.rb +119 -0
- data/lib/ruby_ext/multiple_inheritance.rb +76 -0
- data/lib/ruby_ext/must.rb +192 -0
- data/lib/ruby_ext/not_defined.rb +2 -0
- data/lib/ruby_ext/object.rb +8 -0
- data/lib/ruby_ext/observable2.rb +23 -0
- data/lib/ruby_ext/open_constructor.rb +51 -0
- data/lib/ruby_ext/open_object.rb +157 -0
- data/lib/ruby_ext/prepare_arguments.rb +105 -0
- data/lib/ruby_ext/prototype_inheritance.rb +110 -0
- data/lib/ruby_ext/should.rb +166 -0
- data/lib/ruby_ext/string.rb +44 -0
- data/lib/ruby_ext/symbol.rb +21 -0
- data/lib/ruby_ext/synchronize.rb +24 -0
- data/lib/ruby_ext/tuple.rb +7 -0
- data/lib/ruby_ext.rb +50 -0
- data/lib/spec_ext.rb +10 -0
- data/readme.md +66 -0
- data/spec/_prototype_inheritance_spec.rb +190 -0
- data/spec/array_spec.rb +8 -0
- data/spec/declarative_cache_spec.rb +115 -0
- data/spec/deep_clone_spec.rb +37 -0
- data/spec/helper.rb +20 -0
- data/spec/kernel_spec/TheNamespace/ClassA.rb +7 -0
- data/spec/kernel_spec/another_class.rb +5 -0
- data/spec/kernel_spec/the_namespace/class_b.rb +11 -0
- data/spec/kernel_spec.rb +53 -0
- data/spec/module_spec.rb +160 -0
- data/spec/multiple_inheritance_spec.rb +131 -0
- data/spec/must_spec.rb +29 -0
- data/spec/observable2_spec.rb +42 -0
- data/spec/open_constructor_spec.rb +36 -0
- data/spec/open_object_spec.rb +29 -0
- data/spec/prepare_arguments_spec.rb +46 -0
- data/spec/should_spec.rb +24 -0
- data/spec/spec.opts +2 -0
- data/spec/synchronize_spec.rb +80 -0
- metadata +127 -0
@@ -0,0 +1,166 @@
|
|
1
|
+
class AssertionError < StandardError; end
|
2
|
+
|
3
|
+
Object.class_eval do
|
4
|
+
def should_be! method
|
5
|
+
unless self.send("#{method}?") == true
|
6
|
+
raise AssertionError, "
|
7
|
+
ASSERTION FAILED (#{caller[0]}):
|
8
|
+
#{self.inspect} should be #{method}
|
9
|
+
", caller
|
10
|
+
end
|
11
|
+
|
12
|
+
return self
|
13
|
+
end
|
14
|
+
alias_method :should_have!, :should_be!
|
15
|
+
|
16
|
+
def should_not_be! method
|
17
|
+
unless self.send("#{method}?") == false
|
18
|
+
raise AssertionError, "
|
19
|
+
ASSERTION FAILED (#{caller[0]}):
|
20
|
+
#{self.inspect} should not be #{method}
|
21
|
+
", caller
|
22
|
+
end
|
23
|
+
|
24
|
+
return self
|
25
|
+
end
|
26
|
+
alias_method :should_not_have!, :should_not_be!
|
27
|
+
|
28
|
+
def should! cmd, arg = NotDefined
|
29
|
+
result = case cmd
|
30
|
+
when :be_never_called then
|
31
|
+
false
|
32
|
+
|
33
|
+
when :be_nil then
|
34
|
+
self.equal? nil
|
35
|
+
|
36
|
+
when :be_a
|
37
|
+
if arg.class == Array
|
38
|
+
arg.any?{|klass| self.is_a? klass}
|
39
|
+
else
|
40
|
+
self.is_a? arg
|
41
|
+
end
|
42
|
+
|
43
|
+
when :be_an
|
44
|
+
if arg.class == Array
|
45
|
+
arg.any?{|klass| self.is_a? klass}
|
46
|
+
else
|
47
|
+
self.is_a? arg
|
48
|
+
end
|
49
|
+
|
50
|
+
when :be
|
51
|
+
if arg.class == Array
|
52
|
+
arg.any?{|klass| self.respond_to :is?, klass}
|
53
|
+
else
|
54
|
+
self.respond_to :is?, arg
|
55
|
+
end
|
56
|
+
|
57
|
+
when :include then
|
58
|
+
self.include? arg
|
59
|
+
|
60
|
+
when :be_in then
|
61
|
+
arg.include? self
|
62
|
+
|
63
|
+
when :be_true then
|
64
|
+
self
|
65
|
+
|
66
|
+
when :be_false then
|
67
|
+
!self
|
68
|
+
|
69
|
+
when :be_empty then
|
70
|
+
self.empty?
|
71
|
+
|
72
|
+
else
|
73
|
+
if arg.equal? NotDefined
|
74
|
+
self.send cmd
|
75
|
+
else
|
76
|
+
self.send cmd, arg
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
unless result
|
81
|
+
unless arg.equal? NotDefined
|
82
|
+
raise AssertionError, "
|
83
|
+
ASSERTION FAILED (#{caller[0]}):
|
84
|
+
#{self.inspect} should #{cmd} #{arg.inspect}
|
85
|
+
", caller
|
86
|
+
else
|
87
|
+
raise AssertionError, "
|
88
|
+
ASSERTION FAILED (#{caller[0]}):
|
89
|
+
#{self.inspect} should #{cmd}
|
90
|
+
", caller
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
return self
|
95
|
+
end
|
96
|
+
|
97
|
+
def should_not! cmd, arg = NotDefined
|
98
|
+
result =
|
99
|
+
case cmd
|
100
|
+
when :be_never_called then
|
101
|
+
false
|
102
|
+
|
103
|
+
when :be_nil then
|
104
|
+
self.equal? nil
|
105
|
+
|
106
|
+
when :be_a
|
107
|
+
if arg.class == Array
|
108
|
+
arg.any?{|klass| self.is_a? klass}
|
109
|
+
else
|
110
|
+
self.is_a? arg
|
111
|
+
end
|
112
|
+
|
113
|
+
when :be_an
|
114
|
+
if arg.class == Array
|
115
|
+
arg.any?{|klass| self.is_a? klass}
|
116
|
+
else
|
117
|
+
self.is_a? arg
|
118
|
+
end
|
119
|
+
|
120
|
+
when :be
|
121
|
+
if arg.class == Array
|
122
|
+
arg.any?{|klass| self.respond_to :is?, klass}
|
123
|
+
else
|
124
|
+
self.respond_to :is?, arg
|
125
|
+
end
|
126
|
+
|
127
|
+
when :include then
|
128
|
+
self.include? arg
|
129
|
+
|
130
|
+
when :be_in then
|
131
|
+
arg.include? self
|
132
|
+
|
133
|
+
when :be_true then
|
134
|
+
self
|
135
|
+
|
136
|
+
when :be_false then
|
137
|
+
!self
|
138
|
+
|
139
|
+
when :be_empty then
|
140
|
+
self.empty?
|
141
|
+
|
142
|
+
else
|
143
|
+
if arg.equal? NotDefined
|
144
|
+
self.send cmd
|
145
|
+
else
|
146
|
+
self.send cmd, arg
|
147
|
+
end
|
148
|
+
end
|
149
|
+
|
150
|
+
if result
|
151
|
+
unless arg.equal? NotDefined
|
152
|
+
raise AssertionError, "
|
153
|
+
ASSERTION FAILED (#{caller[0]}):
|
154
|
+
#{self.inspect} should not #{cmd} #{arg.inspect}
|
155
|
+
", caller
|
156
|
+
else
|
157
|
+
raise AssertionError, "
|
158
|
+
ASSERTION FAILED (#{caller[0]}):
|
159
|
+
#{self.inspect} should not #{cmd}
|
160
|
+
", caller
|
161
|
+
end
|
162
|
+
end
|
163
|
+
|
164
|
+
return self
|
165
|
+
end
|
166
|
+
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
String.class_eval do
|
2
|
+
def dirname
|
3
|
+
File.expand_path(File.dirname(self))
|
4
|
+
end
|
5
|
+
|
6
|
+
def parent_dirname
|
7
|
+
File.expand_path(File.dirname(self) + "/..")
|
8
|
+
end
|
9
|
+
|
10
|
+
def to_reader
|
11
|
+
self.to_sym
|
12
|
+
end
|
13
|
+
|
14
|
+
def to_writer
|
15
|
+
"#{self}=".to_sym
|
16
|
+
end
|
17
|
+
|
18
|
+
def to_iv
|
19
|
+
"@#{self}"
|
20
|
+
end
|
21
|
+
|
22
|
+
def interpolate binding
|
23
|
+
binding.must_be.a Binding
|
24
|
+
return gsub(/\#\{.+?\}/) do |term|
|
25
|
+
identifier = term.slice(2 .. term.size-2)
|
26
|
+
binding.eval identifier
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
def self.secure_token
|
31
|
+
original = [Time.now, (1..10).map{ rand.to_s }]
|
32
|
+
Digest::SHA1.hexdigest(original.flatten.join('--'))
|
33
|
+
end
|
34
|
+
|
35
|
+
def underscore
|
36
|
+
word = self.dup
|
37
|
+
word.gsub!(/::/, '/')
|
38
|
+
word.gsub!(/([A-Z]+)([A-Z][a-z])/,'\1_\2')
|
39
|
+
word.gsub!(/([a-z\d])([A-Z])/,'\1_\2')
|
40
|
+
word.tr!("-", "_")
|
41
|
+
word.downcase!
|
42
|
+
word
|
43
|
+
end
|
44
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
Symbol.class_eval do
|
2
|
+
def <=> other
|
3
|
+
self.to_s <=> other.to_s
|
4
|
+
end
|
5
|
+
|
6
|
+
def to_reader
|
7
|
+
self
|
8
|
+
end
|
9
|
+
|
10
|
+
def to_writer
|
11
|
+
"#{self}=".to_sym
|
12
|
+
end
|
13
|
+
|
14
|
+
def to_iv
|
15
|
+
"@#{self}"
|
16
|
+
end
|
17
|
+
|
18
|
+
def + other
|
19
|
+
(self.to_s + other.to_s).to_sym
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
require 'monitor'
|
2
|
+
|
3
|
+
class Module
|
4
|
+
def synchronize_method *methods
|
5
|
+
methods.each do |method|
|
6
|
+
als = "sync_#{escape_method(method)}"
|
7
|
+
|
8
|
+
raise "Can't synchronize the '#{method}' twice!" if instance_methods.include?(als)
|
9
|
+
|
10
|
+
alias_method als, method
|
11
|
+
script = "\
|
12
|
+
def #{method} *p, &b
|
13
|
+
@monitor ||= Monitor.new
|
14
|
+
@monitor.synchronize{#{als} *p, &b}
|
15
|
+
end"
|
16
|
+
class_eval script, __FILE__, __LINE__
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
def synchronize_all_methods include_super = false
|
21
|
+
methods = self.instance_methods(include_super).collect{|m| m.to_sym}
|
22
|
+
synchronize_method *methods
|
23
|
+
end
|
24
|
+
end
|
data/lib/ruby_ext.rb
ADDED
@@ -0,0 +1,50 @@
|
|
1
|
+
core = [
|
2
|
+
'facets/array/indexable', # Array first!, last!
|
3
|
+
'facets/enumerable/every',
|
4
|
+
'facets/enumerable/group_by',
|
5
|
+
'facets/exception/detail', # pretty print
|
6
|
+
'facets/duplicable', # false.dup(), false.clone() and so on.
|
7
|
+
'facets/blank',
|
8
|
+
'facets/numeric/round.rb', # round_at, round_to
|
9
|
+
'facets/hash',
|
10
|
+
'facets/string/interpolate',
|
11
|
+
# 'facets/ostruct',
|
12
|
+
# 'facets/openobject' it has broken implementation and is completelly rewritend in ruby-ext
|
13
|
+
]
|
14
|
+
|
15
|
+
more = [
|
16
|
+
# 'facets/basicobject', causes problem with rspec
|
17
|
+
# 'facets/opencascade', causes problem with redefined OpenObject
|
18
|
+
]
|
19
|
+
|
20
|
+
(core + more).each{|f| require f}
|
21
|
+
|
22
|
+
{
|
23
|
+
:BasicObject => 'basic_object',
|
24
|
+
:OpenObject => 'open_object',
|
25
|
+
:OpenConstructor => 'open_constructor',
|
26
|
+
:Observable2 => 'observable2',
|
27
|
+
:ExtraBlankSlate => 'extra_blank_slate', # do I need it?
|
28
|
+
:Tuple => 'tuple',
|
29
|
+
}.each{|klass, file| Kernel.autoload klass, "ruby_ext/#{file}"}
|
30
|
+
|
31
|
+
%w{
|
32
|
+
file
|
33
|
+
array
|
34
|
+
hash
|
35
|
+
kernel
|
36
|
+
module
|
37
|
+
not_defined
|
38
|
+
object
|
39
|
+
class
|
40
|
+
string
|
41
|
+
symbol
|
42
|
+
|
43
|
+
deep_clone
|
44
|
+
declarative_cache
|
45
|
+
must
|
46
|
+
prepare_arguments
|
47
|
+
synchronize
|
48
|
+
micelaneous
|
49
|
+
multiple_inheritance
|
50
|
+
}.each{|f| require "ruby_ext/#{f}"}
|
data/lib/spec_ext.rb
ADDED
@@ -0,0 +1,10 @@
|
|
1
|
+
require 'spec'
|
2
|
+
|
3
|
+
Spec::Example::ExampleGroup.class_eval do
|
4
|
+
def remove_constants *args
|
5
|
+
args = args.first if args.size == 1 and args.first.is_a?(Array)
|
6
|
+
# args.each{|c| raise "Invalid constant name '#{c}'!" unless c =~ /^[a-z_][a-z_0-9]*$/i}
|
7
|
+
# args = args.first if args.first.is_a?(Array)
|
8
|
+
args.each{|c| Object.send :remove_const, c if Object.const_defined? c}
|
9
|
+
end
|
10
|
+
end
|
data/readme.md
ADDED
@@ -0,0 +1,66 @@
|
|
1
|
+
# Ruby extensions
|
2
|
+
**ruby-ext** is a collection of various utility classes and standard library extensions for the Ruby language.
|
3
|
+
|
4
|
+
## must - assertion tool, kind of RSpec assertions in runtime code
|
5
|
+
|
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
|
+
|
13
|
+
## inherit - combines include & extend in one
|
14
|
+
Do you remember this *def self.included(base) ... end* hack? You don't need it anymore.
|
15
|
+
|
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
|
+
## cache_method & synchronize_method
|
31
|
+
|
32
|
+
def complex_calculation
|
33
|
+
2 * 2
|
34
|
+
end
|
35
|
+
cache_method :complex_calculation
|
36
|
+
|
37
|
+
def money_transfer amount
|
38
|
+
@from -= amount
|
39
|
+
@to += amount
|
40
|
+
end
|
41
|
+
synchronize_method :money_transfer
|
42
|
+
|
43
|
+
## OpenConstructor - adds mass assignment to any class
|
44
|
+
|
45
|
+
class TheClass
|
46
|
+
include OpenConstructor
|
47
|
+
attr_accessor :a, :b
|
48
|
+
end
|
49
|
+
|
50
|
+
o = TheClass.new.set :a => 'a', :b => 'b'
|
51
|
+
o.a => 'a'
|
52
|
+
o.to_hash => {:a => 'a', :b => 'b'}
|
53
|
+
|
54
|
+
## More
|
55
|
+
|
56
|
+
These are just a small part of all handy methods and extensions, for more details please go to specs.
|
57
|
+
|
58
|
+
# Usage
|
59
|
+
|
60
|
+
$ sudo gem install ruby-ext
|
61
|
+
|
62
|
+
require 'ruby_ext'
|
63
|
+
|
64
|
+
Copyright (c) 2009 Alexey Petrushin [http://bos-tec.com](http://bos-tec.com), released under the MIT license.
|
65
|
+
|
66
|
+
[ioc]: http://en.wikipedia.org/wiki/Inversion_of_control
|
@@ -0,0 +1,190 @@
|
|
1
|
+
require "#{File.dirname __FILE__}/helper"
|
2
|
+
require "ruby_ext/prototype_inheritance"
|
3
|
+
|
4
|
+
describe "Prototype Inheritance" do
|
5
|
+
after :each do
|
6
|
+
remove_constants %w(A B C)
|
7
|
+
end
|
8
|
+
|
9
|
+
it "should define and override methods" do
|
10
|
+
class A
|
11
|
+
instance_methods do
|
12
|
+
def instance_method
|
13
|
+
'first version'
|
14
|
+
end
|
15
|
+
end
|
16
|
+
class_methods do
|
17
|
+
def class_method
|
18
|
+
'first version'
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
A.new.instance_method.should == "first version"
|
24
|
+
A.class_method.should == "first version"
|
25
|
+
|
26
|
+
|
27
|
+
A.instance_methods do
|
28
|
+
def instance_method
|
29
|
+
'second version'
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
A.class_methods do
|
34
|
+
def class_method
|
35
|
+
'second version'
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
A.new.instance_method.should == "second version"
|
40
|
+
A.class_method.should == "second version"
|
41
|
+
end
|
42
|
+
|
43
|
+
it "showcase" do
|
44
|
+
class A
|
45
|
+
instance_methods do
|
46
|
+
def a; end
|
47
|
+
|
48
|
+
def overrided_method
|
49
|
+
'a version'
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
class_methods do
|
54
|
+
def class_a; end
|
55
|
+
end
|
56
|
+
|
57
|
+
def self.inherited target
|
58
|
+
target.prototype.send :attr_accessor, :some_accessor
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
class B
|
63
|
+
instance_methods do
|
64
|
+
def b; end
|
65
|
+
|
66
|
+
def overrided_method
|
67
|
+
'b version'
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
class_methods do
|
72
|
+
def class_b; end
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
class C
|
77
|
+
inherit A, B
|
78
|
+
end
|
79
|
+
|
80
|
+
c = C.new
|
81
|
+
c.should respond_to(:a)
|
82
|
+
c.should respond_to(:b)
|
83
|
+
c.should respond_to(:some_accessor)
|
84
|
+
|
85
|
+
C.should respond_to(:class_a)
|
86
|
+
C.should respond_to(:class_b)
|
87
|
+
end
|
88
|
+
|
89
|
+
it "should inherit all ancestors class methods (and take order into account by overriding)" do
|
90
|
+
class A
|
91
|
+
instance_methods do
|
92
|
+
def a; end
|
93
|
+
|
94
|
+
def overrided
|
95
|
+
'a'
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
99
|
+
class_methods do
|
100
|
+
def class_a; end
|
101
|
+
end
|
102
|
+
end
|
103
|
+
|
104
|
+
class B
|
105
|
+
inherit A
|
106
|
+
|
107
|
+
instance_methods do
|
108
|
+
def b; end
|
109
|
+
|
110
|
+
def overrided
|
111
|
+
'b'
|
112
|
+
end
|
113
|
+
end
|
114
|
+
|
115
|
+
class_methods do
|
116
|
+
def class_b; end
|
117
|
+
end
|
118
|
+
end
|
119
|
+
|
120
|
+
class C
|
121
|
+
inherit B
|
122
|
+
end
|
123
|
+
|
124
|
+
c = C.new
|
125
|
+
c.should respond_to(:a)
|
126
|
+
c.should respond_to(:b)
|
127
|
+
c.overrided.should == 'b'
|
128
|
+
|
129
|
+
C.should respond_to(:class_a)
|
130
|
+
C.should respond_to(:class_b)
|
131
|
+
|
132
|
+
C.instance_methods do
|
133
|
+
def overrided
|
134
|
+
'c'
|
135
|
+
end
|
136
|
+
end
|
137
|
+
c = C.new
|
138
|
+
c.overrided.should == 'c'
|
139
|
+
end
|
140
|
+
|
141
|
+
it "shouldn't redefine ancestors class methods (from error)" do
|
142
|
+
class A
|
143
|
+
class_methods do
|
144
|
+
def class_method; end
|
145
|
+
end
|
146
|
+
end
|
147
|
+
|
148
|
+
class B
|
149
|
+
inherit A
|
150
|
+
|
151
|
+
class_methods do
|
152
|
+
def class_method2; end
|
153
|
+
end
|
154
|
+
end
|
155
|
+
|
156
|
+
A.should_not respond_to(:class_method2)
|
157
|
+
end
|
158
|
+
|
159
|
+
it "methods defined on base class after inheritance must be propagated to all descendants" do
|
160
|
+
class A; end
|
161
|
+
|
162
|
+
class B
|
163
|
+
inherit A
|
164
|
+
end
|
165
|
+
|
166
|
+
B.instance_methods.should_not include('method_added_after_inheritance')
|
167
|
+
A.prototype.send(:define_method, :method_added_after_inheritance){}
|
168
|
+
A.instance_methods.should include('method_added_after_inheritance')
|
169
|
+
B.instance_methods.should include('method_added_after_inheritance')
|
170
|
+
end
|
171
|
+
|
172
|
+
it "classes included in base class after inheritance must be propagated to all descendants" do
|
173
|
+
class A; end
|
174
|
+
|
175
|
+
class B
|
176
|
+
inherit A
|
177
|
+
end
|
178
|
+
|
179
|
+
class C
|
180
|
+
instance_methods do
|
181
|
+
def module_added_after_inheritance; end
|
182
|
+
end
|
183
|
+
end
|
184
|
+
|
185
|
+
A.instance_methods.should_not include('module_added_after_inheritance')
|
186
|
+
A.inherit C
|
187
|
+
A.instance_methods.should include('module_added_after_inheritance')
|
188
|
+
B.instance_methods.should include('module_added_after_inheritance')
|
189
|
+
end
|
190
|
+
end
|
data/spec/array_spec.rb
ADDED
@@ -0,0 +1,115 @@
|
|
1
|
+
require "#{File.dirname __FILE__}/helper"
|
2
|
+
require "ruby_ext/declarative_cache"
|
3
|
+
|
4
|
+
describe 'DeclarativeCache' do
|
5
|
+
class CachedClass
|
6
|
+
attr_accessor :value
|
7
|
+
def value_get; @value end
|
8
|
+
cache_method :value_get
|
9
|
+
|
10
|
+
attr_accessor :value2
|
11
|
+
def value2_get; @value2 end
|
12
|
+
|
13
|
+
attr_accessor :params
|
14
|
+
def params_get param; @params[param] end
|
15
|
+
|
16
|
+
attr_accessor :multiplier
|
17
|
+
def *(arg)
|
18
|
+
@multiplier * arg
|
19
|
+
end
|
20
|
+
cache_method_with_params '*'
|
21
|
+
end
|
22
|
+
|
23
|
+
DeclarativeCache.cache_method CachedClass, :value2_get
|
24
|
+
DeclarativeCache.cache_method_with_params CachedClass, :params_get
|
25
|
+
|
26
|
+
it "Simple Cache" do
|
27
|
+
o = CachedClass.new
|
28
|
+
o.value = 0
|
29
|
+
o.value2 = 0
|
30
|
+
o.value_get.should == 0
|
31
|
+
o.value2_get.should == 0
|
32
|
+
|
33
|
+
o.value = 1
|
34
|
+
o.value2 = 1
|
35
|
+
o.value_get.should == 0
|
36
|
+
o.value2_get.should == 0
|
37
|
+
end
|
38
|
+
|
39
|
+
it "clear_cache_method" do
|
40
|
+
o = CachedClass.new
|
41
|
+
o.value = 0
|
42
|
+
o.value_get.should == 0
|
43
|
+
|
44
|
+
o.value = 1
|
45
|
+
o.value_get.should == 0
|
46
|
+
|
47
|
+
o.clear_cache_method
|
48
|
+
o.value_get.should == 1
|
49
|
+
end
|
50
|
+
|
51
|
+
it "should check for parameters" do
|
52
|
+
o = CachedClass.new
|
53
|
+
lambda{o.value_get(1)}.should raise_error(/cache_method_with_params/)
|
54
|
+
end
|
55
|
+
|
56
|
+
it "Cache With Params" do
|
57
|
+
o = CachedClass.new
|
58
|
+
o.params = {:a => :b}
|
59
|
+
o.params_get(:a).should == :b
|
60
|
+
o.params = {:a => :c}
|
61
|
+
o.params_get(:a).should == :b
|
62
|
+
end
|
63
|
+
|
64
|
+
it "should works with operators" do
|
65
|
+
o = CachedClass.new
|
66
|
+
o.multiplier = 2
|
67
|
+
(o * 2).should == 4
|
68
|
+
o.multiplier = 3
|
69
|
+
(o * 2).should == 4
|
70
|
+
end
|
71
|
+
|
72
|
+
class CachedClass2
|
73
|
+
class << self
|
74
|
+
attr_accessor :value
|
75
|
+
def value_get; @value end
|
76
|
+
cache_method :value_get
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
it "Simple Cache" do
|
81
|
+
CachedClass2.value = 0
|
82
|
+
CachedClass2.value_get.should == 0
|
83
|
+
CachedClass2.value = 1
|
84
|
+
CachedClass2.value_get.should == 0
|
85
|
+
end
|
86
|
+
|
87
|
+
module CachedModule
|
88
|
+
attr_accessor :value
|
89
|
+
def value_get; @value end
|
90
|
+
cache_method :value_get
|
91
|
+
end
|
92
|
+
|
93
|
+
class CachedClass3
|
94
|
+
include CachedModule
|
95
|
+
end
|
96
|
+
|
97
|
+
it "should also works with modules (from error)" do
|
98
|
+
o = CachedClass.new
|
99
|
+
o.value = 0
|
100
|
+
o.value_get.should == 0
|
101
|
+
|
102
|
+
o.value = 1
|
103
|
+
o.value_get.should == 0
|
104
|
+
end
|
105
|
+
|
106
|
+
class CachedClass4
|
107
|
+
attr_accessor :value
|
108
|
+
def value_get; @value end
|
109
|
+
end
|
110
|
+
|
111
|
+
it "should not allow to cache twice" do
|
112
|
+
CachedClass4.cache_method :value_get
|
113
|
+
lambda{CachedClass4.cache_method :value_get}.should raise_error(/twice/)
|
114
|
+
end
|
115
|
+
end
|