method_decorators 0.9.3 → 0.9.4
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.travis.yml +3 -3
- data/README.md +9 -3
- data/lib/method_decorators/deprecated.rb +84 -0
- data/lib/method_decorators/memoize.rb +8 -1
- data/lib/method_decorators/version.rb +1 -1
- data/spec/decorators/deprecated.rb +115 -0
- data/spec/decorators/memoize_spec.rb +15 -0
- data/spec/decorators/within_spec.rb +2 -2
- data/spec/method_decorators_spec.rb +2 -2
- metadata +24 -18
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 6785de47236233823f549e66f287ee890f124a26
|
4
|
+
data.tar.gz: 4ecf3e013b9f697ae331f0b437141527a8cf9d09
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 20d7254686c1318bf47f5c652c2ca58fbfcd00beb215beebaa506997a0c36c4428e3c5074cec2783ba7a344a30aff039395fc24143e8ba1a5bd65148b7526bce
|
7
|
+
data.tar.gz: da3881d7736c32a1ecc9412b1fcacef497f7668d0d34a412bb5a758dbc1ab4f3f738b35aaf6858950600e0bcd3a766cc76dc60ee4194bdf0b79abaa22d82f05b
|
data/.travis.yml
CHANGED
data/README.md
CHANGED
@@ -2,6 +2,8 @@
|
|
2
2
|
|
3
3
|
Python's function decorators for Ruby.
|
4
4
|
|
5
|
+
I probably wouldn't use this in production.
|
6
|
+
|
5
7
|
## Installation
|
6
8
|
`gem install method_decorators`
|
7
9
|
|
@@ -11,11 +13,13 @@ Python's function decorators for Ruby.
|
|
11
13
|
Extend MethodDecorators in a class where you want to use them, and then stick `+DecoratorName` before your method declaration to decorate the method.
|
12
14
|
|
13
15
|
```ruby
|
14
|
-
|
16
|
+
require "method_decorators/memoize"
|
17
|
+
|
18
|
+
class MyMath
|
15
19
|
extend MethodDecorators
|
16
20
|
|
17
|
-
+MethodDecorators::
|
18
|
-
def fib(n)
|
21
|
+
+MethodDecorators::Memoize
|
22
|
+
def self.fib(n)
|
19
23
|
if n <= 1
|
20
24
|
1
|
21
25
|
else
|
@@ -23,6 +27,8 @@ class Math
|
|
23
27
|
end
|
24
28
|
end
|
25
29
|
end
|
30
|
+
|
31
|
+
puts MyMath.fib(200)
|
26
32
|
```
|
27
33
|
|
28
34
|
You can also decorate with an instance of a decorator, rather than the class. This is useful for configuring specific options for the decorator.
|
@@ -0,0 +1,84 @@
|
|
1
|
+
require 'method_decorators'
|
2
|
+
|
3
|
+
module MethodDecorators
|
4
|
+
# Example:
|
5
|
+
# class MyClass
|
6
|
+
# extend MethodDecorators
|
7
|
+
#
|
8
|
+
# +MethodDecorators::Deprecated
|
9
|
+
# def deprecated_method
|
10
|
+
# brand_new_method
|
11
|
+
# end
|
12
|
+
# end
|
13
|
+
# When deprecated_method is called, message
|
14
|
+
# "MyClass#deprecated_method is deprecated"
|
15
|
+
# is output.
|
16
|
+
#
|
17
|
+
# Another example:
|
18
|
+
# class MyClass
|
19
|
+
# extend MethodDecorators
|
20
|
+
#
|
21
|
+
# +MethodDecorators::Deprecated.new('deprecated_method will be removed in the future')
|
22
|
+
# def deprecated_method
|
23
|
+
# brand_new_method
|
24
|
+
# end
|
25
|
+
# end
|
26
|
+
# Above output given message
|
27
|
+
# "deprecated_method will be removed in the future"
|
28
|
+
#
|
29
|
+
# Custom message example:
|
30
|
+
# class MyClass
|
31
|
+
# extend MethodDecorators
|
32
|
+
#
|
33
|
+
# +MethodDecorators::Deprecated.new {|class_name, method_name| "#{class_name}##{method_name} will be removed in the future. Use #{class_name}#brand_new_method instead"}
|
34
|
+
# def deprecated_method
|
35
|
+
# brand_new_method
|
36
|
+
# end
|
37
|
+
# end
|
38
|
+
# Outputs
|
39
|
+
# "MyClass#deprecated_method will be removed in the future. Use MyClass#brand_new_method instead"
|
40
|
+
# As you see, you can use class name as the first argument and method name as the second in the block.
|
41
|
+
#
|
42
|
+
# Formatter example:
|
43
|
+
# class Formatter2
|
44
|
+
# def call(class_name, method_name)
|
45
|
+
# "#{class_name}##{method_name} will be removed after the next version. Use #{class_name}#brand_new_method instead"
|
46
|
+
# end
|
47
|
+
# end
|
48
|
+
# class MyClass
|
49
|
+
# extend MethodDecorators
|
50
|
+
#
|
51
|
+
# formatter1 = ->(class_mane, method_name) {"#{class_name}##{method_name} will be removed in the next version. Use #{class_name}#brand_new_method instead"}
|
52
|
+
# +MethodDecorators::Deprecated.new(formatter1)
|
53
|
+
# def very_old_method
|
54
|
+
# brand_new_method
|
55
|
+
# end
|
56
|
+
#
|
57
|
+
# + MethodDecorators::Deprecated.new(Formatter2.new)
|
58
|
+
# def deprecated_method
|
59
|
+
# brand_new_method
|
60
|
+
# end
|
61
|
+
# end
|
62
|
+
# Outputs
|
63
|
+
# "MyClass#deprecated_method will be removed in the future. Use MyClass#brand_new_method instead"
|
64
|
+
# You can give any object which responds to method "call" like Proc.
|
65
|
+
class Deprecated < Decorator
|
66
|
+
DEFAULT_FORMATTER = lambda {|class_name, method_name| "#{class_name}##{method_name} is deprecated"}
|
67
|
+
def initialize(message=nil, &blk)
|
68
|
+
@message = message || blk || DEFAULT_FORMATTER
|
69
|
+
end
|
70
|
+
|
71
|
+
def call(orig, this, *args, &blk)
|
72
|
+
warn message(this.class, orig.name)
|
73
|
+
orig.call(*args, &blk)
|
74
|
+
end
|
75
|
+
|
76
|
+
def message(class_name, method_name)
|
77
|
+
if @message.respond_to? :call
|
78
|
+
@message.call(class_name, method_name)
|
79
|
+
else
|
80
|
+
@message.to_s
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|
@@ -2,6 +2,10 @@ require "method_decorators"
|
|
2
2
|
|
3
3
|
module MethodDecorators
|
4
4
|
class Memoize < Decorator
|
5
|
+
def initialize
|
6
|
+
@memo_ivar = "@_memoize_cache#{rand(10**10)}"
|
7
|
+
end
|
8
|
+
|
5
9
|
def call(orig, this, *args, &blk)
|
6
10
|
return cache(this)[args] if cache(this).has_key?(args)
|
7
11
|
cache(this)[args] = orig.call(*args, &blk)
|
@@ -9,7 +13,10 @@ module MethodDecorators
|
|
9
13
|
|
10
14
|
private
|
11
15
|
def cache(this)
|
12
|
-
|
16
|
+
memo_ivar = @memo_ivar
|
17
|
+
this.instance_eval do
|
18
|
+
instance_variable_get(memo_ivar) || instance_variable_set(memo_ivar, {})
|
19
|
+
end
|
13
20
|
end
|
14
21
|
end
|
15
22
|
end
|
@@ -0,0 +1,115 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'method_decorators/deprecated'
|
3
|
+
require 'stringio'
|
4
|
+
|
5
|
+
describe MethodDecorators::Deprecated do
|
6
|
+
let(:method) { double(:method, :call => 'return value of original method', :name => 'deprecated_method') }
|
7
|
+
|
8
|
+
describe '#call' do
|
9
|
+
subject { MethodDecorators::Deprecated.new }
|
10
|
+
|
11
|
+
it 'calls original method' do
|
12
|
+
method.should_receive(:call)
|
13
|
+
subject.call(method, nil)
|
14
|
+
end
|
15
|
+
|
16
|
+
it 'warns' do
|
17
|
+
subject.should_receive(:warn)
|
18
|
+
subject.call(method, nil)
|
19
|
+
end
|
20
|
+
|
21
|
+
context 'when string given on initializing' do
|
22
|
+
subject { MethodDecorators::Deprecated.new('custom message') }
|
23
|
+
|
24
|
+
it 'warns with given string' do
|
25
|
+
subject.should_receive(:warn).with('custom message')
|
26
|
+
subject.call(method, nil)
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
context 'when block given on initializing' do
|
31
|
+
subject { MethodDecorators::Deprecated.new {|klass, method| "#{klass}##{method}"} }
|
32
|
+
|
33
|
+
it 'warns with message formatted by the block' do
|
34
|
+
subject.should_receive(:warn).with('NilClass#deprecated_method')
|
35
|
+
subject.call(method, nil)
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
context 'when object which has #call method given on initializing' do
|
40
|
+
subject { MethodDecorators::Deprecated.new(lambda { |klass, method| "#{klass}##{method}" }) }
|
41
|
+
|
42
|
+
it 'warns with message formatted by the object' do
|
43
|
+
subject.should_receive(:warn).with('NilClass#deprecated_method')
|
44
|
+
subject.call(method, nil)
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
describe 'acceptance' do
|
50
|
+
before do
|
51
|
+
$stderr = StringIO.new
|
52
|
+
subject.deprecated_method
|
53
|
+
$stderr.rewind
|
54
|
+
end
|
55
|
+
|
56
|
+
let(:klass) {
|
57
|
+
Class.new Base do
|
58
|
+
+MethodDecorators::Deprecated
|
59
|
+
def deprecated_method
|
60
|
+
'return value of original method'
|
61
|
+
end
|
62
|
+
end
|
63
|
+
}
|
64
|
+
subject { klass.new }
|
65
|
+
|
66
|
+
it 'warns' do
|
67
|
+
expect($stderr.read).to eq("#{klass}#deprecated_method is deprecated\n")
|
68
|
+
end
|
69
|
+
|
70
|
+
context 'when string given on initializing' do
|
71
|
+
let(:klass) {
|
72
|
+
Class.new Base do
|
73
|
+
+MethodDecorators::Deprecated.new('custom message')
|
74
|
+
def deprecated_method
|
75
|
+
'return value of original method'
|
76
|
+
end
|
77
|
+
end
|
78
|
+
}
|
79
|
+
|
80
|
+
it 'warns with given string' do
|
81
|
+
expect($stderr.read).to eq("custom message\n")
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
context 'when block given on initializing' do
|
86
|
+
let(:klass) {
|
87
|
+
Class.new Base do
|
88
|
+
+MethodDecorators::Deprecated.new {|class_name, method_name| "#{class_name}##{method_name} is deprecated"}
|
89
|
+
def deprecated_method
|
90
|
+
'return value of original method'
|
91
|
+
end
|
92
|
+
end
|
93
|
+
}
|
94
|
+
|
95
|
+
it 'warns with message formatted by the block' do
|
96
|
+
expect($stderr.read).to eq("#{klass}#deprecated_method is deprecated\n")
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
100
|
+
context 'when object witch has #call method givn on initializing' do
|
101
|
+
let(:klass) {
|
102
|
+
Class.new Base do
|
103
|
+
+MethodDecorators::Deprecated.new(lambda { |class_name, method_name| "#{class_name}##{method_name} is deprecated" })
|
104
|
+
def deprecated_method
|
105
|
+
'return value of original method'
|
106
|
+
end
|
107
|
+
end
|
108
|
+
}
|
109
|
+
|
110
|
+
it 'warns with message formatted by the object' do
|
111
|
+
expect($stderr.read).to eq("#{klass}#deprecated_method is deprecated\n")
|
112
|
+
end
|
113
|
+
end
|
114
|
+
end
|
115
|
+
end
|
@@ -43,6 +43,16 @@ describe MethodDecorators::Memoize do
|
|
43
43
|
@count += 1
|
44
44
|
rand
|
45
45
|
end
|
46
|
+
|
47
|
+
+MethodDecorators::Memoize
|
48
|
+
def zero
|
49
|
+
0
|
50
|
+
end
|
51
|
+
|
52
|
+
+MethodDecorators::Memoize
|
53
|
+
def one
|
54
|
+
1
|
55
|
+
end
|
46
56
|
end
|
47
57
|
end
|
48
58
|
subject { klass.new }
|
@@ -54,6 +64,11 @@ describe MethodDecorators::Memoize do
|
|
54
64
|
#subject.count.should == 1
|
55
65
|
end
|
56
66
|
|
67
|
+
it "memoizes call to different methods separately" do
|
68
|
+
subject.zero.should eql 0
|
69
|
+
subject.one.should eql 1
|
70
|
+
end
|
71
|
+
|
57
72
|
context "with two instances of the decorated class" do
|
58
73
|
let(:o1) { subject }
|
59
74
|
let(:o2) { klass.new }
|
@@ -13,7 +13,7 @@ describe MethodDecorators::Within do
|
|
13
13
|
|
14
14
|
it "does not raise when the method has finished execution before timeout" do
|
15
15
|
method.stub(:call){ sleep 1 }
|
16
|
-
expect{ subject.call(method, nil) }.to_not raise_error
|
16
|
+
expect{ subject.call(method, nil) }.to_not raise_error
|
17
17
|
end
|
18
18
|
end
|
19
19
|
|
@@ -36,7 +36,7 @@ describe MethodDecorators::Within do
|
|
36
36
|
|
37
37
|
context "with shorter execution period" do
|
38
38
|
it "finishes within the timeout period" do
|
39
|
-
expect{ subject.do_it(1) }.to_not raise_error
|
39
|
+
expect{ subject.do_it(1) }.to_not raise_error
|
40
40
|
end
|
41
41
|
end
|
42
42
|
end
|
@@ -96,7 +96,7 @@ describe MethodDecorators do
|
|
96
96
|
|
97
97
|
it "works" do
|
98
98
|
subject.six.should == '6'
|
99
|
-
end
|
99
|
+
end
|
100
100
|
end
|
101
101
|
|
102
102
|
describe "that takes args" do
|
@@ -193,7 +193,7 @@ describe MethodDecorators do
|
|
193
193
|
|
194
194
|
it "works" do
|
195
195
|
subject.six.should == '6'
|
196
|
-
end
|
196
|
+
end
|
197
197
|
end
|
198
198
|
|
199
199
|
describe "that takes args" do
|
metadata
CHANGED
@@ -1,38 +1,43 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: method_decorators
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.9.
|
5
|
-
prerelease:
|
4
|
+
version: 0.9.4
|
6
5
|
platform: ruby
|
7
6
|
authors:
|
8
7
|
- Michael Fairley
|
9
8
|
autorequire:
|
10
9
|
bindir: bin
|
11
10
|
cert_chain: []
|
12
|
-
date:
|
11
|
+
date: 2014-01-29 00:00:00.000000000 Z
|
13
12
|
dependencies:
|
14
13
|
- !ruby/object:Gem::Dependency
|
15
14
|
name: rake
|
16
|
-
requirement:
|
17
|
-
none: false
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
18
16
|
requirements:
|
19
|
-
- -
|
17
|
+
- - '>='
|
20
18
|
- !ruby/object:Gem::Version
|
21
19
|
version: '0'
|
22
20
|
type: :development
|
23
21
|
prerelease: false
|
24
|
-
version_requirements:
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - '>='
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '0'
|
25
27
|
- !ruby/object:Gem::Dependency
|
26
28
|
name: rspec
|
27
|
-
requirement:
|
28
|
-
none: false
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
29
30
|
requirements:
|
30
|
-
- -
|
31
|
+
- - '>='
|
31
32
|
- !ruby/object:Gem::Version
|
32
33
|
version: '0'
|
33
34
|
type: :development
|
34
35
|
prerelease: false
|
35
|
-
version_requirements:
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - '>='
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '0'
|
36
41
|
description: Python's function decorators for Ruby
|
37
42
|
email:
|
38
43
|
- michaelfairley@gmail.com
|
@@ -56,12 +61,14 @@ files:
|
|
56
61
|
- lib/method_decorators/decorators/memoize.rb
|
57
62
|
- lib/method_decorators/decorators/precondition.rb
|
58
63
|
- lib/method_decorators/decorators/retry.rb
|
64
|
+
- lib/method_decorators/deprecated.rb
|
59
65
|
- lib/method_decorators/memoize.rb
|
60
66
|
- lib/method_decorators/precondition.rb
|
61
67
|
- lib/method_decorators/retry.rb
|
62
68
|
- lib/method_decorators/version.rb
|
63
69
|
- lib/method_decorators/within.rb
|
64
70
|
- method_decorators.gemspec
|
71
|
+
- spec/decorators/deprecated.rb
|
65
72
|
- spec/decorators/memoize_spec.rb
|
66
73
|
- spec/decorators/precondition_spec.rb
|
67
74
|
- spec/decorators/retry_spec.rb
|
@@ -73,29 +80,29 @@ files:
|
|
73
80
|
- spec/support/stringify.rb
|
74
81
|
homepage: http://github.com/michaelfairley/method_decorators
|
75
82
|
licenses: []
|
83
|
+
metadata: {}
|
76
84
|
post_install_message:
|
77
85
|
rdoc_options: []
|
78
86
|
require_paths:
|
79
87
|
- lib
|
80
88
|
required_ruby_version: !ruby/object:Gem::Requirement
|
81
|
-
none: false
|
82
89
|
requirements:
|
83
|
-
- -
|
90
|
+
- - '>='
|
84
91
|
- !ruby/object:Gem::Version
|
85
92
|
version: '0'
|
86
93
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
87
|
-
none: false
|
88
94
|
requirements:
|
89
|
-
- -
|
95
|
+
- - '>='
|
90
96
|
- !ruby/object:Gem::Version
|
91
97
|
version: '0'
|
92
98
|
requirements: []
|
93
99
|
rubyforge_project:
|
94
|
-
rubygems_version:
|
100
|
+
rubygems_version: 2.0.3
|
95
101
|
signing_key:
|
96
|
-
specification_version:
|
102
|
+
specification_version: 4
|
97
103
|
summary: Python's function decorators for Ruby
|
98
104
|
test_files:
|
105
|
+
- spec/decorators/deprecated.rb
|
99
106
|
- spec/decorators/memoize_spec.rb
|
100
107
|
- spec/decorators/precondition_spec.rb
|
101
108
|
- spec/decorators/retry_spec.rb
|
@@ -105,4 +112,3 @@ test_files:
|
|
105
112
|
- spec/support/add_n.rb
|
106
113
|
- spec/support/reverse.rb
|
107
114
|
- spec/support/stringify.rb
|
108
|
-
has_rdoc:
|