method_decorators 0.9.3 → 0.9.4
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.
- 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:
|