duck_puncher 2.12.0 → 2.12.1
Sign up to get free protection for your applications and to get access to all the features.
- 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 [![Gem Version](https://badge.fury.io/rb/duck_puncher.svg)](http://badge.fury.io/rb/duck_puncher) [![Build Status](https://travis-ci.org/ridiculous/duck_puncher.svg)](https://travis-ci.org/ridiculous/duck_puncher) [![Code Climate](https://codeclimate.com/github/ridiculous/duck_puncher/badges/gpa.svg)](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
|