duck_puncher 4.0.0 → 4.1.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: f945aea9eb0db7392e51aea5cda254eaad6d5815
4
- data.tar.gz: fa1e7a2565caee23e437d38b60358f9fbf382901
3
+ metadata.gz: 1cb44e09391f847e93e57bcf8440f2c2d15ed047
4
+ data.tar.gz: 3ce4e5424e681138720017420ac9acf62fb813d2
5
5
  SHA512:
6
- metadata.gz: 3c05f53aad5478fda527751c1cc3625cf6d0dad18397a08311610d56a13ada9fab6705623f7ae8fec63902636f78255cee3ad3fd892e9b0ada44c9132bba3d3e
7
- data.tar.gz: b7310b2c603075ce345f24805bb4d2dc7211515c86b69dc0df775d8aa362cf723c656b3a22a8a0696d0a2fd1b6294e7b96c6a91511d26eb35ea61956865f74c4
6
+ metadata.gz: 21f328e2955ba0a5d22edb8182ebba32707413aff62e0f788bc87fe5bf889317d601d44cc809cdfb1edb3e8029777080124e26f57b65e0a6b499e0b51c775960
7
+ data.tar.gz: 1de4fb69952aec16f29c3bfa6034cf4400b5aea73d64bbfee6f7b735c0149e4fb5cd278cacd2d45dfbd4bd7a27faf29117a2ef55393520f2cbbe95b8820b27e7
@@ -4,7 +4,7 @@ module DuckPuncher
4
4
  @decorators ||= ancestral_hash
5
5
  end
6
6
 
7
- def new_decorator(*ducks)
7
+ def build_decorator_class(*ducks)
8
8
  targets = ducks.sort.map(&:target)
9
9
  decorator_class = DelegateClass(targets.first)
10
10
  DuckPuncher.redefine_constant "#{targets.first.to_s.tr(':', '')}Delegator", decorator_class
@@ -12,6 +12,16 @@ module DuckPuncher
12
12
  decorator_class
13
13
  end
14
14
 
15
+ def decorate(context, target)
16
+ cached_decorators[target].inject(context) { |me, (_, decorator)| decorator.new(me) }
17
+ end
18
+
19
+ def cached_decorators
20
+ @cached_decorators ||= Hash.new do |me, target|
21
+ me[target] = DuckPuncher.decorators.select { |klass, _| klass >= target }.sort { |a, b| b[0] <=> a[0] }
22
+ end
23
+ end
24
+
15
25
  def undecorate(obj)
16
26
  obj = obj.__getobj__ while obj.respond_to? :__getobj__
17
27
  obj
@@ -11,16 +11,17 @@ module DuckPuncher
11
11
  end
12
12
  end
13
13
 
14
- # @description Returns a new decorated version of ourself with the punches mixed in
14
+ # @description Returns a new decorated version of ourself with the punches mixed in (adds ancestors decorators)
15
15
  # @return [<self.class>Delegator]
16
16
  def punch
17
- DuckPuncher.decorators[DuckPuncher.undecorate(self).class].new(self)
17
+ DuckPuncher.decorate self, DuckPuncher.undecorate(self).class
18
18
  end
19
19
 
20
20
  # @description Adds the duck punches to the current object (meant to be used on instances, careful with nil and numbers!)
21
21
  # @return self
22
22
  def punch!
23
- DuckPuncher::Ducks.load_mods(DuckPuncher.undecorate(self).class).each { |mod| self.extend mod }
23
+ target = DuckPuncher.undecorate(self).class
24
+ DuckPuncher::Ducks.load_mods(target).each { |mod| self.extend mod }
24
25
  self
25
26
  end
26
27
 
@@ -7,15 +7,15 @@ module DuckPuncher
7
7
  Array(mods).each do |mod|
8
8
  duck = Duck.new target, mod, options
9
9
  Ducks.list[target] << duck
10
- decorators[target] = new_decorator(duck, *Ducks[target])
10
+ decorators[target] = build_decorator_class(duck, *Ducks[target])
11
11
  end
12
- nil
12
+ @cached_decorators = nil
13
13
  end
14
14
 
15
15
  def deregister(*classes)
16
16
  classes.each &Ducks.list.method(:delete)
17
17
  classes.each &decorators.method(:delete)
18
- nil
18
+ @cached_decorators = nil
19
19
  end
20
20
  end
21
21
  end
@@ -1,3 +1,3 @@
1
1
  module DuckPuncher
2
- VERSION = '4.0.0'.freeze
2
+ VERSION = '4.1.0'.freeze
3
3
  end
@@ -57,4 +57,22 @@ class ObjectTest < MiniTest::Test
57
57
  assert_respond_to @kaia, :talk
58
58
  assert_respond_to @kaia, :quack
59
59
  end
60
+
61
+ def test_soft_punch_includes_all_ancestors
62
+ DuckPuncher.register Animal, CustomPunch2
63
+ DuckPuncher.register Dog, CustomPunch
64
+ DuckPuncher.register Kaia, CustomPunch3
65
+ @kaia = Kaia.new.punch
66
+ assert_respond_to @kaia, :wobble
67
+ assert_respond_to @kaia, :talk
68
+ assert_respond_to @kaia, :quack
69
+ end
70
+
71
+ def test_soft_punch_with_parent_override
72
+ DuckPuncher.register Animal, CustomPunch
73
+ DuckPuncher.register Kaia, ModWithOverride
74
+ @kaia = Kaia.new.punch
75
+ assert_respond_to @kaia, :talk
76
+ assert_equal @kaia.talk, 'talk is cheap'
77
+ end
60
78
  end
data/test/test_helper.rb CHANGED
@@ -25,6 +25,12 @@ module CustomPunch3
25
25
  end
26
26
  end
27
27
 
28
+ module ModWithOverride
29
+ def talk
30
+ 'talk is cheap'
31
+ end
32
+ end
33
+
28
34
  module ModWithNestedMod
29
35
  def instance_method_1
30
36
  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: 4.0.0
4
+ version: 4.1.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-08-17 00:00:00.000000000 Z
11
+ date: 2016-08-18 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: usable