duck_puncher 2.12.0 → 2.12.1
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 +4 -4
- data/README.md +49 -67
- data/lib/duck_puncher.rb +4 -2
- data/lib/duck_puncher/version.rb +1 -1
- data/test/lib/duck_puncher_test.rb +11 -11
- data/test/test_helper.rb +17 -0
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 9e0baa8b465ab3c4158735e6bc53c37f0bbf6883
|
4
|
+
data.tar.gz: 34c8cf5c21031da525db6133dbec50e3d4840f26
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 202f6cc91ff336089c3761334add4ab4503bd358fef5aa9310fb555545a3b980701ef8db4504b3af75207baa1871956365e1c4dd6cfc1a09c3ad85ee0a8dc136
|
7
|
+
data.tar.gz: 8f431ff2ca0ecd65c040842d803edb06012baf39c90d0a806f32c42bed21b57a4677b249659abd5401a0a7d166e74a0e110ac4789a58cf48f7302e16610f0b51
|
data/README.md
CHANGED
@@ -1,9 +1,12 @@
|
|
1
1
|
# DuckPuncher [](http://badge.fury.io/rb/duck_puncher) [](https://travis-ci.org/ridiculous/duck_puncher) [](https://codeclimate.com/github/ridiculous/duck_puncher)
|
2
2
|
|
3
|
-
|
4
|
-
tough love! :punch: :heart:
|
3
|
+
DuckPuncher provides an interface for administering __duck punches__ (a.k.a "monkey patches"). Punches can be administered in several ways:
|
5
4
|
|
6
|
-
|
5
|
+
* as an extension
|
6
|
+
* as a subclass
|
7
|
+
* as a decorator
|
8
|
+
|
9
|
+
Default extensions:
|
7
10
|
|
8
11
|
```ruby
|
9
12
|
Array #m => `[].m(:to_s)` => `[].map(&:to_s)`
|
@@ -22,35 +25,35 @@ Method #to_instruct => `Benchmark.method(:measure).to_instruct` returns the Ru
|
|
22
25
|
#to_source => `Benchmark.method(:measure).to_source` returns the method definition as a string
|
23
26
|
```
|
24
27
|
|
25
|
-
##
|
28
|
+
## Usage
|
26
29
|
|
27
|
-
Punch
|
30
|
+
Punch all registered ducks:
|
28
31
|
|
29
32
|
```ruby
|
30
|
-
|
31
|
-
=> nil
|
32
|
-
>> 100.to_currency '$'
|
33
|
-
=> "$100.00"
|
34
|
-
>> 100.to_duration
|
35
|
-
=> "1 min"
|
36
|
-
>> 100.to_time_ago
|
37
|
-
NoMethodError: undefined method `to_time_ago' for 100:Fixnum
|
33
|
+
DuckPuncher.punch_all!
|
38
34
|
```
|
39
35
|
|
40
|
-
|
36
|
+
Punch individual ducks by name:
|
41
37
|
|
42
|
-
|
38
|
+
```ruby
|
39
|
+
DuckPuncher.punch! :Hash, :Object
|
40
|
+
```
|
43
41
|
|
44
|
-
|
42
|
+
One method to rule them all:
|
45
43
|
|
46
44
|
```ruby
|
47
|
-
DuckPuncher.
|
48
|
-
DuckPuncher.punch! :Hash, :Object # => only punches the Hash and Object ducks
|
49
|
-
DuckPuncher.punch! :Object, only: :punch # => only opens a can of whoop ass! Define one method to rule them all
|
45
|
+
DuckPuncher.punch! :Object, only: :punch
|
50
46
|
```
|
51
47
|
|
52
|
-
|
53
|
-
|
48
|
+
### Tactical punches
|
49
|
+
|
50
|
+
Punch only certain methods onto a duck:
|
51
|
+
|
52
|
+
```ruby
|
53
|
+
DuckPuncher.punch! :Numeric, only: [:to_currency, :to_duration]
|
54
|
+
```
|
55
|
+
|
56
|
+
The `.punch` method creates and caches a new punched class that __inherits__ from the original:
|
54
57
|
|
55
58
|
```ruby
|
56
59
|
>> DuckPuncher.punch :String
|
@@ -61,7 +64,7 @@ classes. For example:
|
|
61
64
|
=> false
|
62
65
|
```
|
63
66
|
|
64
|
-
If you punch `Object` then you can use `punch` on any object to get a new
|
67
|
+
If you punch `Object` then you can use `punch` on any object to get a new __decorated__ copy of the object with the desired
|
65
68
|
functionality mixed in:
|
66
69
|
|
67
70
|
```ruby
|
@@ -72,78 +75,57 @@ functionality mixed in:
|
|
72
75
|
|
73
76
|
Because `DuckPuncher` extends the amazing [Usable](https://github.com/ridiculous/usable) gem, you can configure only the punches you want!
|
74
77
|
|
75
|
-
|
78
|
+
### Registering custom punches
|
76
79
|
|
77
|
-
DuckPuncher allows you to utilize the `punch` interface to
|
78
|
-
`.register` with the name of your module
|
80
|
+
DuckPuncher allows you to utilize the `punch` interface to __decorate__ any kind of object with your own punches. Simply
|
81
|
+
call `.register` with the name of your module (or an array of names) and any of
|
82
|
+
[these options](https://github.com/ridiculous/duck_puncher/blob/master/lib/duck_puncher/duck.rb#L11).
|
79
83
|
|
80
|
-
### Punching your own duck
|
81
|
-
```ruby
|
82
|
-
class User < Struct.new(:name)
|
83
|
-
end
|
84
84
|
|
85
|
+
```ruby
|
86
|
+
# Define some extensions
|
85
87
|
module Billable
|
86
|
-
def
|
88
|
+
def call(amt)
|
87
89
|
puts "Attempting to bill #{name} for $#{amt}"
|
88
90
|
fail Errno::ENOENT
|
89
91
|
end
|
90
92
|
end
|
91
93
|
|
92
94
|
module Retryable
|
93
|
-
def
|
94
|
-
|
95
|
+
def call_with_retry(*args, retries: 3)
|
96
|
+
call *args
|
95
97
|
rescue Errno::ENOENT
|
96
98
|
puts 'retrying'
|
97
99
|
retry if (retries -= 1) > 0
|
98
100
|
end
|
99
101
|
end
|
100
102
|
|
101
|
-
|
102
|
-
DuckPuncher.register :Retryable
|
103
|
-
DuckPuncher.punch! :Object, only: :punch
|
104
|
-
|
105
|
-
user = User.new('Ryan').punch(:Billable).punch(:Retryable)
|
106
|
-
user.perform_with_retry(19.99)
|
107
|
-
```
|
103
|
+
# Register the extensions
|
104
|
+
DuckPuncher.register [:Billable, :Retryable]
|
108
105
|
|
109
|
-
|
110
|
-
|
111
|
-
# Example punches
|
112
|
-
module Donald
|
113
|
-
def tap_tap
|
114
|
-
p self
|
115
|
-
self
|
116
|
-
end
|
106
|
+
# Our duck
|
107
|
+
class User < Struct.new(:name)
|
117
108
|
end
|
118
109
|
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
110
|
+
# Add the #punch method to User instances
|
111
|
+
DuckPuncher.punch! :Object, only: :punch, target: User
|
112
|
+
|
113
|
+
# Usage
|
114
|
+
user = User.new('Ryan').punch(:Billable).punch(:Retryable)
|
115
|
+
user.call_with_retry(19.99)
|
124
116
|
```
|
125
117
|
|
126
|
-
When punching a class, the `:class` option is required
|
118
|
+
When punching at a class level, the `:class` option is required:
|
127
119
|
|
128
120
|
```ruby
|
129
|
-
DuckPuncher.register :
|
130
|
-
DuckPuncher.punch! :
|
131
|
-
[].tap_tap
|
121
|
+
DuckPuncher.register :Billable, class: 'User'
|
122
|
+
DuckPuncher.punch! :Billable
|
132
123
|
```
|
133
124
|
|
134
|
-
|
125
|
+
## Install
|
135
126
|
|
136
|
-
|
137
|
-
DuckPuncher.punch! :Object, only: :punch
|
138
|
-
DuckPuncher.register :Donald
|
139
|
-
DuckPuncher.register :Daisy
|
140
|
-
ducks = [].punch(:Donald).punch(:Daisy)
|
141
|
-
ducks.tap_tap
|
142
|
-
ducks.quack
|
143
|
-
```
|
127
|
+
gem 'duck_puncher'
|
144
128
|
|
145
|
-
The `register` method takes the same options as [Duck#initialize](https://github.com/ridiculous/duck_puncher/blob/master/lib/duck_puncher/duck.rb#L11)
|
146
|
-
and will be used to configure punches.
|
147
129
|
|
148
130
|
## Experimental
|
149
131
|
|
data/lib/duck_puncher.rb
CHANGED
@@ -47,7 +47,7 @@ module DuckPuncher
|
|
47
47
|
options = names.last.is_a?(Hash) ? names.pop : {}
|
48
48
|
names.each do |name|
|
49
49
|
duck = Ducks[name]
|
50
|
-
log.warn %Q(Punching#{" #{options[:only]} onto" if Array(options[:only]).any?} #{name})
|
50
|
+
log.warn %Q(Punching#{" #{options[:only]} onto" if Array(options[:only]).any?} #{options.fetch(:target, name)})
|
51
51
|
unless duck.punch(options)
|
52
52
|
log.error %Q(Failed to punch #{name}!)
|
53
53
|
end
|
@@ -61,7 +61,9 @@ module DuckPuncher
|
|
61
61
|
end
|
62
62
|
|
63
63
|
def register(*args)
|
64
|
-
|
64
|
+
Array(args.shift).each do |name|
|
65
|
+
Ducks.list << Duck.new(name, *args)
|
66
|
+
end
|
65
67
|
end
|
66
68
|
end
|
67
69
|
|
data/lib/duck_puncher/version.rb
CHANGED
@@ -1,17 +1,6 @@
|
|
1
1
|
require_relative '../test_helper'
|
2
2
|
|
3
|
-
module CustomPunch
|
4
|
-
def tap_tap
|
5
|
-
p self
|
6
|
-
self
|
7
|
-
end
|
8
|
-
end
|
9
|
-
|
10
3
|
class DuckPuncherTest < MiniTest::Test
|
11
|
-
def teardown
|
12
|
-
Object.send :remove_const, :CustomPunch
|
13
|
-
end
|
14
|
-
|
15
4
|
def test_register
|
16
5
|
refute_respond_to [], :tap_tap
|
17
6
|
DuckPuncher.register :CustomPunch, class: 'Array'
|
@@ -20,4 +9,15 @@ class DuckPuncherTest < MiniTest::Test
|
|
20
9
|
DuckPuncher.punch! :Object, only: :punch
|
21
10
|
assert_respond_to [].punch(:CustomPunch), :tap_tap
|
22
11
|
end
|
12
|
+
|
13
|
+
def test_register_with_array
|
14
|
+
refute_respond_to [], :quack
|
15
|
+
refute_respond_to [], :wobble
|
16
|
+
DuckPuncher.register [:CustomPunch2, :CustomPunch3], class: 'Array'
|
17
|
+
DuckPuncher.punch! :CustomPunch2
|
18
|
+
assert_respond_to [], :quack
|
19
|
+
refute_respond_to [], :wobble
|
20
|
+
DuckPuncher.punch! :CustomPunch3
|
21
|
+
assert_respond_to [], :wobble
|
22
|
+
end
|
23
23
|
end
|
data/test/test_helper.rb
CHANGED
@@ -4,3 +4,20 @@ require 'minitest/reporters'
|
|
4
4
|
require 'duck_puncher'
|
5
5
|
|
6
6
|
Minitest::Reporters.use!
|
7
|
+
|
8
|
+
module CustomPunch
|
9
|
+
def tap_tap
|
10
|
+
p self
|
11
|
+
self
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
module CustomPunch2
|
16
|
+
def quack
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
module CustomPunch3
|
21
|
+
def wobble
|
22
|
+
end
|
23
|
+
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: duck_puncher
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.12.
|
4
|
+
version: 2.12.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Ryan Buckley
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2016-
|
11
|
+
date: 2016-03-01 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: usable
|