duck_puncher 2.11.0 → 2.12.0

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 810a0e182430aafb5d23731ac2d01a456675073b
4
- data.tar.gz: faf6bff2544dd61bbf9a91bebcfc6bba7609ec13
3
+ metadata.gz: 5df7873691d0800251c6f01efa662ff8ffe5951f
4
+ data.tar.gz: 8143c677f0dab3351ed2f19c94b575efc6058682
5
5
  SHA512:
6
- metadata.gz: b266c73a702ae2086b0bf603bd48cbd3b972e238b46319eaa25c1e2c8a1eb21027297156eb1e7f6abe00393f5b3aab0a5b7f34dd08c8b0a0cb70c4f01353632b
7
- data.tar.gz: 1a5977e96defe3c647581d8440c1721efccd1da9b4435bf8e8839175a5c3fdd8649772d43f7fce6afa731b7394653671befa58547f084a8ef2c779d3df2cc8a5
6
+ metadata.gz: bb8741aacf58c8f481df8b7976fc263f128d2d27c56deab4b734f08dab0400ed9a8e48b592d0e692f2d25d0f223b07ca64d3a3002ea898d7956eb6d83747be01
7
+ data.tar.gz: 43e29a239f7ca340ccc0aa64abd36097d81e3ab6088866eb28bd9b6f6dfd395cf0b8b9e46ae38ca098f52b639a3e6ad9245514607bfb95f8fb9665fab98ab450
data/README.md CHANGED
@@ -17,18 +17,17 @@ Numeric #to_currency => `25.245.to_currency` => 25.25
17
17
  String #pluralize => `'hour'.pluralize(2)` => "hours"
18
18
  #underscore => `'DuckPuncher::JSONStorage'.underscore` => 'duck_puncher/json_storage'
19
19
  Object #clone! => `Object.new.clone!` => a deep clone of the object (using Marshal.dump)
20
- #punch => `'duck'.punch` => a copy of 'duck' with the mixed String punches
20
+ #punch => `'duck'.punch` => a copy of 'duck' with String punches mixed in
21
21
  Method #to_instruct => `Benchmark.method(:measure).to_instruct` returns the Ruby VM instruction sequence for the method
22
22
  #to_source => `Benchmark.method(:measure).to_source` returns the method definition as a string
23
23
  ```
24
24
 
25
25
  ## Tactical punches
26
26
 
27
- Sometimes you don't want to punch all the ducks. That's why you can punch only certain methods onto a class:
27
+ Punch only certain methods onto a duck:
28
28
 
29
29
  ```ruby
30
30
  >> DuckPuncher.punch! :Numeric, only: [:to_currency, :to_duration]
31
- WARN: Punching [:to_currency, :to_duration] onto Numeric
32
31
  => nil
33
32
  >> 100.to_currency '$'
34
33
  => "$100.00"
@@ -44,11 +43,8 @@ NoMethodError: undefined method `to_time_ago' for 100:Fixnum
44
43
 
45
44
  ## Usage
46
45
 
47
- Ducks need to be _loaded_ before they can be punched! Maybe put this in an initializer:
48
-
49
46
  ```ruby
50
- # config/initializers/duck_puncher.rb
51
- DuckPuncher.punch_all! # => punches all the ducks forever
47
+ DuckPuncher.punch_all! # => punches all registered ducks
52
48
  DuckPuncher.punch! :Hash, :Object # => only punches the Hash and Object ducks
53
49
  DuckPuncher.punch! :Object, only: :punch # => only opens a can of whoop ass! Define one method to rule them all
54
50
  ```
@@ -79,9 +75,40 @@ Because `DuckPuncher` extends the amazing [Usable](https://github.com/ridiculous
79
75
  ## Registering custom punches
80
76
 
81
77
  DuckPuncher allows you to utilize the `punch` interface to decorate any kind of object with your own punches. Simply call
82
- `.register` with the name of your module:
78
+ `.register` with the name of your module.
79
+
80
+ ### Punching your own duck
81
+ ```ruby
82
+ class User < Struct.new(:name)
83
+ end
84
+
85
+ module Billable
86
+ def perform(amt)
87
+ puts "Attempting to bill #{name} for $#{amt}"
88
+ fail Errno::ENOENT
89
+ end
90
+ end
91
+
92
+ module Retryable
93
+ def perform_with_retry(*args, retries: 3)
94
+ perform *args
95
+ rescue Errno::ENOENT
96
+ puts 'retrying'
97
+ retry if (retries -= 1) > 0
98
+ end
99
+ end
100
+
101
+ DuckPuncher.register :Billable
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
+ ```
83
108
 
109
+ ### Punching core ducks
84
110
  ```ruby
111
+ # Example punches
85
112
  module Donald
86
113
  def tap_tap
87
114
  p self
@@ -94,33 +121,30 @@ module Daisy
94
121
  "Hi, I'm Daisy"
95
122
  end
96
123
  end
97
-
98
- DuckPuncher.register :Donald, class: 'Array', if: -> { 'some condition' }
99
- DuckPuncher.register :Daisy, class: 'Array'
100
124
  ```
101
125
 
102
- The register method takes the same options as [Duck#initialize](https://github.com/ridiculous/duck_puncher/blob/master/lib/duck_puncher/duck.rb#L11)
103
- and will be used to configure punches.
104
-
105
- Activate a custom punch:
126
+ When punching a class, the `:class` option is required when registering:
106
127
 
107
128
  ```ruby
129
+ DuckPuncher.register :Donald, class: 'Array'
108
130
  DuckPuncher.punch! :Donald
109
131
  [].tap_tap
110
- # or
111
- DuckPuncher.punch! :Object, only: :punch
112
- [].punch(:Donald).tap_tap
113
132
  ```
114
133
 
115
- Punches can also be stacked together:
134
+ When punching instances, the `:class` option can be omitted, but the name of the punch is required:
116
135
 
117
136
  ```ruby
118
137
  DuckPuncher.punch! :Object, only: :punch
138
+ DuckPuncher.register :Donald
139
+ DuckPuncher.register :Daisy
119
140
  ducks = [].punch(:Donald).punch(:Daisy)
120
141
  ducks.tap_tap
121
142
  ducks.quack
122
143
  ```
123
144
 
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
+
124
148
  ## Experimental
125
149
 
126
150
  __Object#require!__ will try to require a gem, or, if it's not found, then _download_ it! It will also keep track of any
@@ -136,7 +160,6 @@ LoadError: cannot load such file -- pry
136
160
  from (irb):1
137
161
  from bin/console:10:in `<main>'
138
162
  >> DuckPuncher.punch! :Object, only: :require!
139
- WARN: Punching require! onto Object
140
163
  => nil
141
164
  >> require! 'pry'
142
165
  Fetching: method_source-0.8.2.gem (100%)
@@ -196,5 +219,10 @@ Duck.track
196
219
 
197
220
  * Fork it
198
221
  * Run tests with `rake`
199
- * Start an IRB console that already has all your ducks in a row `bin/console`
222
+ * Start an IRB console that already has all your ducks in a row: `bin/console`
223
+ * Start an IRB console without punching ducks: `PUNCH=no bin/console`
200
224
  * Make changes and submit a PR to [https://github.com/ridiculous/duck_puncher](https://github.com/ridiculous/duck_puncher)
225
+
226
+ ## License
227
+
228
+ MIT
data/bin/console CHANGED
@@ -7,6 +7,8 @@ require 'irb'
7
7
  require 'byebug'
8
8
  require_relative '../test/fixtures/wut'
9
9
 
10
+ DuckPuncher.log.level = Logger::DEBUG
11
+
10
12
  if ENV['PUNCH'] != 'no'
11
13
  DuckPuncher.punch_all!
12
14
  end
data/lib/duck_puncher.rb CHANGED
@@ -56,7 +56,7 @@ module DuckPuncher
56
56
  end
57
57
 
58
58
  def punch_all!
59
- log.warn 'Punching all ducks! Watch out!'
59
+ log.warn 'Punching all ducks!'
60
60
  Ducks.list.each &:punch
61
61
  end
62
62
 
@@ -65,13 +65,10 @@ module DuckPuncher
65
65
  end
66
66
  end
67
67
 
68
- # @description Default logger
69
- # @example Silence logging
70
- #
71
- # `DuckPuncher.log.level = Logger::ERROR`
72
- #
73
68
  self.log = Logger.new(STDOUT).tap do |config|
74
69
  config.level = Logger::INFO
75
70
  config.formatter = proc { |*args| "#{args.first}: #{args.last.to_s}\n" }
76
71
  end
72
+
73
+ log.level = Logger::ERROR
77
74
  end
@@ -18,7 +18,7 @@ module DuckPuncher
18
18
  # @option options [Array,Symbol] :only Specifies the methods to extend onto the current object
19
19
  def punch(opts = {})
20
20
  if options[:if] && !options[:if].call
21
- DuckPuncher.log.warn %Q(Failed to punch #{name}!)
21
+ DuckPuncher.log.info %Q(Skipping the punch for #{name}!)
22
22
  return nil
23
23
  end
24
24
  target = opts.delete(:target) || klass
@@ -15,7 +15,7 @@ module DuckPuncher
15
15
 
16
16
  def [](name)
17
17
  list.find { |duck| duck.name == name.to_sym } ||
18
- DuckPuncher.log.info(%Q(Couldn't find "#{name}" in my list of Ducks! I know about: #{list.map(&:name).map(&:to_s)}))
18
+ DuckPuncher.log.warn(%Q(Couldn't find "#{name}" in my list of Ducks! I know about: #{list.map(&:name).map(&:to_s)}))
19
19
  end
20
20
 
21
21
  def load_path_for(duck)
@@ -11,7 +11,7 @@ class DuckPuncher::GemInstaller
11
11
  begin
12
12
  require spec[:require_with]
13
13
  rescue LoadError => e
14
- DuckPuncher.log.warn "Failed to load #{spec[:require_with]} from .duck_puncher/ #{e.inspect}"
14
+ DuckPuncher.log.error "Failed to load #{spec[:require_with]} from .duck_puncher/ #{e.inspect}"
15
15
  end
16
16
  end
17
17
  end
@@ -1,3 +1,3 @@
1
1
  module DuckPuncher
2
- VERSION = '2.11.0'.freeze
2
+ VERSION = '2.12.0'.freeze
3
3
  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.11.0
4
+ version: 2.12.0
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-02-24 00:00:00.000000000 Z
11
+ date: 2016-02-27 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: usable