decoratable 0.0.1 → 0.0.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.travis.yml +4 -3
- data/README.rdoc +100 -0
- data/decoratable.gemspec +3 -1
- data/lib/decoratable/deprecatable.rb +12 -0
- data/lib/decoratable.rb +6 -0
- data/test/decoratable/deprecatable_test.rb +40 -0
- data/test/decoratable_test.rb +1 -3
- metadata +35 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: ec20dff74a6642c85271dcb977529bcd33ca8174
|
4
|
+
data.tar.gz: 9ff3c561a008fff52d078a61ec2ab68630756580
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: c940d91c425fd100b43d850ae9e78522ae385a5dc9a52bd321b73c82b8f2f8411e6f4a53597699c657d4a5647d359cf15e30c70abc7198161494f74eeee5d65a
|
7
|
+
data.tar.gz: 6ef5795b503abba017d278c6bfdcd52c3d04d1929d99a7901829d0f09b14ac10e6db41c87188de9cf4d24d41c19e1b01e6ae3d123986948478bc5445596acba2
|
data/.travis.yml
CHANGED
data/README.rdoc
ADDED
@@ -0,0 +1,100 @@
|
|
1
|
+
= Decoratable
|
2
|
+
|
3
|
+
Provides an easy way to define decorations that add common behaviour to your methods.
|
4
|
+
|
5
|
+
== Installation
|
6
|
+
|
7
|
+
gem install decoratable
|
8
|
+
|
9
|
+
== Requirements
|
10
|
+
|
11
|
+
Decoratable does its magic via Module#prepend, which means:
|
12
|
+
|
13
|
+
* MRI (1.9.3 and up) OR
|
14
|
+
* JRuby 9000
|
15
|
+
|
16
|
+
== Usage
|
17
|
+
|
18
|
+
require "decoratable"
|
19
|
+
|
20
|
+
module Retryable
|
21
|
+
# All methods defined in this module can decorate methods
|
22
|
+
extend Decoratable
|
23
|
+
|
24
|
+
def retryable(tries = 1, options = { on: [RuntimeError] })
|
25
|
+
attempt = 0
|
26
|
+
# To invoke the original method, simply use `yield`
|
27
|
+
yield
|
28
|
+
rescue *options[:on]
|
29
|
+
attempt += 1
|
30
|
+
attempt > tries ? raise : retry
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
module Pryable
|
35
|
+
extend Decoratable
|
36
|
+
|
37
|
+
def pryable
|
38
|
+
yield
|
39
|
+
rescue => e
|
40
|
+
require "pry"
|
41
|
+
binding.pry
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
module Measurable
|
46
|
+
extend Decoratable
|
47
|
+
|
48
|
+
def measurable(logger = Logger.new(STDOUT))
|
49
|
+
start = Time.now
|
50
|
+
yield
|
51
|
+
ensure
|
52
|
+
# The decoration has access to the original method
|
53
|
+
# args and any block passed in the original method call are also available
|
54
|
+
# via __args__ and __block__ respectively
|
55
|
+
original_method = __decorated_method__
|
56
|
+
|
57
|
+
method_location, line = original_method.source_location
|
58
|
+
marker = "#{original_method.owner}##{original_method.name}[#{method_location}:#{line}]"
|
59
|
+
duration = (Time.now - start).round(2)
|
60
|
+
|
61
|
+
logger.info "#{marker} took #{duration}s to run."
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
class Client
|
66
|
+
extend Measurable
|
67
|
+
extend Pryable
|
68
|
+
extend Retryable
|
69
|
+
|
70
|
+
# This method will automatically retry on TimeoutErrors, up to 3 times
|
71
|
+
retryable(tries = 3, on: [TimeoutError])
|
72
|
+
def get
|
73
|
+
…
|
74
|
+
end
|
75
|
+
|
76
|
+
# If an error is raised in this method, we'll automatically get a pry session
|
77
|
+
# to help us debug it
|
78
|
+
pryable
|
79
|
+
def post
|
80
|
+
…
|
81
|
+
end
|
82
|
+
|
83
|
+
# Log the time this method takes to run
|
84
|
+
measurable
|
85
|
+
def delete
|
86
|
+
…
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
Decoratable provides a handful of decorations as part of the gem:
|
91
|
+
|
92
|
+
* require "decoratable/countable": keep a count each time a method gets called
|
93
|
+
* require "decoratable/debuggable": open a Ruby debug console (i.e. require "debug") if an error is raised
|
94
|
+
* require "decoratable/deprecatable": log a warning whenever a deprecated method gets called; logs the caller's location
|
95
|
+
* require "decoratable/hintable": add type hinting to your method arguments
|
96
|
+
* require "decoratable/memoizable": automatically memoize the return value of a method
|
97
|
+
* require "decoratable/pryable": open a Pry debug console (i.e. binding.pry) if an error is raised
|
98
|
+
* require "decoratable/retryable": automatically retry a number of times when a specified exception is raised
|
99
|
+
|
100
|
+
More to be added as time goes on.
|
data/decoratable.gemspec
CHANGED
@@ -3,7 +3,7 @@ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
|
3
3
|
|
4
4
|
Gem::Specification.new do |spec|
|
5
5
|
spec.name = "decoratable"
|
6
|
-
spec.version = "0.0.
|
6
|
+
spec.version = "0.0.2"
|
7
7
|
spec.authors = ["ecin"]
|
8
8
|
spec.email = ["ecin@copypastel.com"]
|
9
9
|
spec.description = "Decorate your methods."
|
@@ -16,5 +16,7 @@ Gem::Specification.new do |spec|
|
|
16
16
|
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
17
17
|
spec.require_paths = ["lib"]
|
18
18
|
|
19
|
+
spec.add_development_dependency "minitest"
|
19
20
|
spec.add_development_dependency "pry"
|
21
|
+
spec.add_development_dependency "rake", ">= 10.0.0"
|
20
22
|
end
|
@@ -0,0 +1,12 @@
|
|
1
|
+
require "decoratable"
|
2
|
+
|
3
|
+
require "logger"
|
4
|
+
|
5
|
+
module Deprecatable
|
6
|
+
extend Decoratable
|
7
|
+
|
8
|
+
def deprecatable(logger = Logger.new(STDOUT))
|
9
|
+
logger.warn("#{__decorated_method__.name} is deprecated. Called from: #{__original_caller__[0]}")
|
10
|
+
yield
|
11
|
+
end
|
12
|
+
end
|
data/lib/decoratable.rb
CHANGED
@@ -91,6 +91,10 @@ module Decoratable
|
|
91
91
|
alias_method "method_added_without_#{decoration_name}", :method_added
|
92
92
|
end
|
93
93
|
|
94
|
+
unless method_defined?(:__original_caller__)
|
95
|
+
define_method(:__original_caller__) { @__original_caller__ }
|
96
|
+
end
|
97
|
+
|
94
98
|
unless method_defined?(:__decorated_method__)
|
95
99
|
define_method(:__decorated_method__) { @__decorated_method__ }
|
96
100
|
end
|
@@ -126,6 +130,7 @@ module Decoratable
|
|
126
130
|
@__decorated_method__ = original_method
|
127
131
|
@__args__ = args
|
128
132
|
@__block__ = block
|
133
|
+
@__original_caller__ ||= caller
|
129
134
|
|
130
135
|
decoration_method.bind(self).call(*decorator_args) do
|
131
136
|
super(*args, &block)
|
@@ -134,6 +139,7 @@ module Decoratable
|
|
134
139
|
@__decorated_method__ = nil
|
135
140
|
@__args__ = nil
|
136
141
|
@__block__ = nil
|
142
|
+
@__original_caller__ = nil
|
137
143
|
end
|
138
144
|
end
|
139
145
|
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
require "test_helper"
|
2
|
+
|
3
|
+
require "decoratable/deprecatable"
|
4
|
+
require "decoratable/retryable"
|
5
|
+
require "decoratable/memoizable"
|
6
|
+
|
7
|
+
describe Deprecatable do
|
8
|
+
extend Memoizable
|
9
|
+
|
10
|
+
before do
|
11
|
+
# Need to assign to a local variable so it's accessible from
|
12
|
+
# the following class definition scope.
|
13
|
+
logger = mock_logger
|
14
|
+
|
15
|
+
klass = Class.new do
|
16
|
+
extend Deprecatable
|
17
|
+
extend Retryable
|
18
|
+
|
19
|
+
deprecatable(logger)
|
20
|
+
def old_method; end
|
21
|
+
end
|
22
|
+
|
23
|
+
@object = klass.new
|
24
|
+
end
|
25
|
+
|
26
|
+
it "prints a warning when a method is called" do
|
27
|
+
# If the `@object.old_method` line moves around, we'll have to modify the line arithmetic for the
|
28
|
+
# expected regex.
|
29
|
+
mock_logger.expect(:warn, nil, [/old_method is deprecated\. Called from: #{__FILE__}:#{__LINE__ + 2}/])
|
30
|
+
|
31
|
+
@object.old_method
|
32
|
+
mock_logger.verify
|
33
|
+
end
|
34
|
+
|
35
|
+
# Reusing library code in a test? Amazing!
|
36
|
+
memoizable
|
37
|
+
def mock_logger
|
38
|
+
Minitest::Mock.new
|
39
|
+
end
|
40
|
+
end
|
data/test/decoratable_test.rb
CHANGED
@@ -142,9 +142,7 @@ describe Decoratable do
|
|
142
142
|
|
143
143
|
def mock_logger
|
144
144
|
logger = Minitest::Mock.new
|
145
|
-
logger.expect(:info, nil
|
146
|
-
message =~ /took \d+\.\d+s to run/
|
147
|
-
end
|
145
|
+
logger.expect(:info, nil, [/took \d+\.\d+s to run/])
|
148
146
|
logger
|
149
147
|
end
|
150
148
|
end
|
metadata
CHANGED
@@ -1,15 +1,29 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: decoratable
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- ecin
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2016-11-26 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: minitest
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ">="
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '0'
|
20
|
+
type: :development
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - ">="
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '0'
|
13
27
|
- !ruby/object:Gem::Dependency
|
14
28
|
name: pry
|
15
29
|
requirement: !ruby/object:Gem::Requirement
|
@@ -24,6 +38,20 @@ dependencies:
|
|
24
38
|
- - ">="
|
25
39
|
- !ruby/object:Gem::Version
|
26
40
|
version: '0'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: rake
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - ">="
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: 10.0.0
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - ">="
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: 10.0.0
|
27
55
|
description: Decorate your methods.
|
28
56
|
email:
|
29
57
|
- ecin@copypastel.com
|
@@ -33,16 +61,19 @@ extra_rdoc_files: []
|
|
33
61
|
files:
|
34
62
|
- ".travis.yml"
|
35
63
|
- Gemfile
|
64
|
+
- README.rdoc
|
36
65
|
- Rakefile
|
37
66
|
- decoratable.gemspec
|
38
67
|
- lib/decoratable.rb
|
39
68
|
- lib/decoratable/countable.rb
|
40
69
|
- lib/decoratable/debuggable.rb
|
70
|
+
- lib/decoratable/deprecatable.rb
|
41
71
|
- lib/decoratable/hintable.rb
|
42
72
|
- lib/decoratable/memoizable.rb
|
43
73
|
- lib/decoratable/pryable.rb
|
44
74
|
- lib/decoratable/retryable.rb
|
45
75
|
- test/decoratable/countable_test.rb
|
76
|
+
- test/decoratable/deprecatable_test.rb
|
46
77
|
- test/decoratable/hintable_test.rb
|
47
78
|
- test/decoratable/memoizable_test.rb
|
48
79
|
- test/decoratable/pryable_test.rb
|
@@ -69,16 +100,16 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
69
100
|
version: '0'
|
70
101
|
requirements: []
|
71
102
|
rubyforge_project:
|
72
|
-
rubygems_version: 2.
|
103
|
+
rubygems_version: 2.5.1
|
73
104
|
signing_key:
|
74
105
|
specification_version: 4
|
75
106
|
summary: Easily define decorations for your methods. Put a bow on it.
|
76
107
|
test_files:
|
77
108
|
- test/decoratable/countable_test.rb
|
109
|
+
- test/decoratable/deprecatable_test.rb
|
78
110
|
- test/decoratable/hintable_test.rb
|
79
111
|
- test/decoratable/memoizable_test.rb
|
80
112
|
- test/decoratable/pryable_test.rb
|
81
113
|
- test/decoratable/retryable_test.rb
|
82
114
|
- test/decoratable_test.rb
|
83
115
|
- test/test_helper.rb
|
84
|
-
has_rdoc:
|