method_decorator 2.0.0 → 2.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: 607f30fb2f44469cac0ff14b5b6dd1bfa80164ef
4
- data.tar.gz: 09ead13f5c6c41d17b7c9cc129d7ee9a1d324ccc
3
+ metadata.gz: b76ea850afa9489fa5475cb52dce8f6884215b6a
4
+ data.tar.gz: 9a05e1374523166287151e6790b66e5701ae9c09
5
5
  SHA512:
6
- metadata.gz: 8a2ce94d7ad57315caaa659efa8c621168943db20b656115469254b10850c4dc73bc038eea00b5394ce499df6d5a95618d757d47e134482a753311e8c53ed120
7
- data.tar.gz: 973c2a671be37ebcc7bd3924d3e2d581eeb9cc6740dc84fcdaeff99b800e806691635cc0c45f2c0815668cbd6023bfe71907915e1b001b4bccbc4a609f652d83
6
+ metadata.gz: 7c088113e4a0803b007944eba4781cd8655f2d907be4a9fcd3493583faa688868b30521706057e2b4b89b39a17e8adfc55d4ece2bac25f85a2bb6c91bb1650cf
7
+ data.tar.gz: b46674adf3ff149e6fe00ff5bff6df99415ea6a4b7650f96e7d98d090660b52d6dfd04cce6ebb1a772a699ec065c11c8abaf3ea04eaf8574f2d8714fab28d26f
data/README.rdoc CHANGED
@@ -1,9 +1,11 @@
1
1
  = Method Decorator
2
2
 
3
- Provides a way to dynamically overwrite methods without losing original behavior.
3
+ Provides a way to dynamically override methods without losing original behavior.
4
4
 
5
5
  == Example
6
6
 
7
+ For a given class:
8
+
7
9
  class SomeClass
8
10
 
9
11
  def some_method(some_arg)
@@ -14,7 +16,7 @@ Provides a way to dynamically overwrite methods without losing original behavior
14
16
 
15
17
  MethodDecorator.decorate SomeClass, :some_method do |*args|
16
18
  puts :decorated_some_method
17
- MethodDecorator.call_original self, :some_method, *args
19
+ MethodDecorator.call_original_method self, :some_method, *args
18
20
  end
19
21
 
20
22
  This call:
@@ -44,7 +46,7 @@ It works too:
44
46
 
45
47
  MethodDecorator.decorate SomeClass.singleton_class, :some_method do |*args|
46
48
  puts :decorated_some_method
47
- MethodDecorator.call_original self, :some_method, *args
49
+ MethodDecorator.call_original_method self, :some_method, *args
48
50
  end
49
51
 
50
52
  SomeClass.some_method 'some arg'
@@ -1,11 +1,11 @@
1
1
  module MethodDecorator
2
2
  class Decoration
3
3
 
4
- attr_accessor :target_class, :target_name, :target_method, :decoration
4
+ attr_accessor :target_class, :target_method_name, :target_method, :decoration
5
5
 
6
- def initialize(target_class, target_method_name, target_method)
6
+ def initialize(target_class, target_method_name, target_method, &decoration)
7
7
  self.target_class = target_class
8
- self.target_name = target_method_name
8
+ self.target_method_name = target_method_name
9
9
  self.target_method = target_method
10
10
  self.decoration = block_given? ? Proc.new : nil
11
11
  end
@@ -6,22 +6,25 @@ module MethodDecorator
6
6
 
7
7
  attr_writer :decorations
8
8
 
9
- def add_decoration(target_class, target_name, &decoration)
10
- exists = original_method target_class, target_name
11
- target_method = target_class.instance_method target_name
12
- decoration = Decoration.new target_class, target_name, target_method, &decoration
13
- self.decorations.push(decoration) unless exists
9
+ def add(target_class, target_method_name, target_method, &decoration)
10
+ exists = original_target_method_of target_class, target_method_name
11
+
12
+ self.decorations.push(
13
+ Decoration.new target_class, target_method_name, target_method, &decoration
14
+ ) unless exists
15
+
14
16
  not exists
15
17
  end
16
18
 
17
- def original_method(target_class, target_name)
18
- condition = Proc.new { |d| d.target_class.eql?(target_class) and d.target_name.eql?(target_name) }
19
- decoration = self.decorations.select(&condition).first
19
+ def original_target_method_of(target_class, target_method_name)
20
+ decoration = self.decorations.select do
21
+ |d| d.target_class.eql?(target_class) and d.target_method_name.eql?(target_method_name)
22
+ end.first
23
+
20
24
  decoration ? decoration.target_method : nil
21
25
  end
22
26
 
23
27
  def decorations; @decorations ||= [] end
24
-
25
28
  end
26
29
  end
27
30
  end
@@ -1,3 +1,3 @@
1
1
  module MethodDecorator
2
- VERSION = '2.0.0'
2
+ VERSION = '2.1.0'
3
3
  end
@@ -1,29 +1,55 @@
1
1
  require 'method_decorator/repository'
2
2
 
3
3
  module MethodDecorator
4
+
4
5
  class << self
5
6
 
6
- def decorate(target_class, target_name, &decoration)
7
- added = Repository.add_decoration target_class, target_name, &decoration
8
- target_class.send :define_method, target_name, &decoration if added
7
+ def decorate(target_class, target_method_name, &decoration)
8
+ raise 'target_method_name must be a symbol' unless target_method_name.is_a? Symbol
9
+ added = add_to_repository(decoration, target_class, target_method_name)
10
+ override_method(decoration, target_class, target_method_name) if added
9
11
  added
10
12
  end
11
13
 
12
- def call_original(target_context, target_name, *original_args, &original_block)
13
- target_class = target_class target_context
14
- target_method = Repository.original_method target_class, target_name
15
- target_method.bind(target_context).call *original_args, &original_block
14
+ protected
15
+
16
+ def add_to_repository(decoration, target_class, target_method_name)
17
+ Repository.add(
18
+ target_class,
19
+ target_method_name,
20
+ target_class.instance_method(target_method_name),
21
+ &decoration
22
+ )
23
+ end
24
+
25
+ def override_method(decoration, target_class, target_method_name)
26
+ is_protected = target_class.protected_instance_methods.include? target_method_name
27
+ is_private = target_class.private_instance_methods.include? target_method_name
28
+ target_class.send :define_method, target_method_name, &decoration
29
+ target_class.instance_eval { protected target_method_name } if is_protected
30
+ target_class.instance_eval { private target_method_name } if is_private
16
31
  end
17
32
 
18
- def target_class(target_context)
19
- target_type(target_context).eql?(:singleton) ?
20
- target_context.singleton_class :
21
- target_context.class
33
+ public
34
+
35
+ def call_original_method(target_context, target_method_name, *original_args, &original_block)
36
+ target_class = target_class_from_context(target_context)
37
+ target_method = Repository.original_target_method_of(target_class, target_method_name)
38
+ target_method.bind(target_context).call(*original_args, &original_block)
39
+ end
40
+
41
+ def target_class_from_context(target_context)
42
+ if target_type_from_context(target_context).eql? :singleton
43
+ target_context.singleton_class
44
+ else
45
+ target_context.class
46
+ end
22
47
  end
23
48
 
24
- def target_type(target_context)
49
+ def target_type_from_context(target_context)
25
50
  target_context.class.eql?(Class) ? :singleton : :class
26
51
  end
27
52
 
28
53
  end
54
+
29
55
  end
@@ -1,26 +1,116 @@
1
1
  require 'spec_helper'
2
- require 'support/some_class'
2
+ require 'support/dummy_class'
3
3
 
4
4
  describe MethodDecorator do
5
5
 
6
- let(:some_arg) { :some_arg }
6
+ let(:dummy_arg) { :dummy_arg }
7
7
 
8
- subject { target.some_method some_arg }
8
+ context 'when common class as target' do
9
9
 
10
- before do
11
- expect(target).to receive(:puts).with(:decorated_some_method).ordered
12
- expect(target).to receive(:puts).with(some_arg).ordered
13
- end
10
+ let(:target) { DummyClass }
11
+ let(:target_instance) { target.new }
12
+
13
+ context 'when public method' do
14
+
15
+ before { expect(target_instance).to receive(:puts).with(:a_decorated_public_instance_method).ordered }
16
+ before { expect(target_instance).to receive(:puts).with("a_public_instance_method_arg: #{dummy_arg}").ordered }
17
+
18
+ it { target_instance.a_public_instance_method dummy_arg }
19
+
20
+ end
21
+
22
+ context 'when protected method' do
23
+
24
+ context 'when calling protected method deliberately' do
25
+
26
+ it { expect{target_instance.a_protected_instance_method dummy_arg}.to raise_error NoMethodError }
27
+
28
+ end
29
+
30
+ context 'when calling protected method through `send`' do
31
+
32
+ before { expect(target_instance).to receive(:puts).with(:a_decorated_protected_instance_method).ordered }
33
+ before { expect(target_instance).to receive(:puts).with("a_protected_instance_method_arg: #{dummy_arg}").ordered }
34
+
35
+ it { target_instance.send :a_protected_instance_method, dummy_arg }
36
+
37
+ end
38
+
39
+ end
40
+
41
+ context 'when private method' do
42
+
43
+ context 'when calling private method deliberately' do
44
+
45
+ it { expect{target_instance.a_private_instance_method dummy_arg}.to raise_error NoMethodError }
46
+
47
+ end
48
+
49
+ context 'when calling private method through `send`' do
50
+
51
+ before { expect(target_instance).to receive(:puts).with(:a_decorated_private_instance_method).ordered }
52
+ before { expect(target_instance).to receive(:puts).with("a_private_instance_method_arg: #{dummy_arg}").ordered }
53
+
54
+ it { target_instance.send :a_private_instance_method, dummy_arg }
55
+
56
+ end
57
+
58
+ end
14
59
 
15
- context 'when singleton method context' do
16
- let(:target) { SomeClass }
17
- it { subject }
18
60
  end
19
61
 
20
- context 'when instance method context' do
21
- let(:target) { SomeClass.new }
22
- let(:methods) { target.class.send :generated_methods }
23
- it { subject }
62
+ context 'when singleton class as target' do
63
+
64
+ let(:target) { DummyClass.singleton_class }
65
+ let(:target_instance) { DummyClass }
66
+
67
+ context 'when public method' do
68
+
69
+ before { expect(target_instance).to receive(:puts).with(:a_decorated_public_singleton_method).ordered }
70
+ before { expect(target_instance).to receive(:puts).with("a_public_singleton_method_arg: #{dummy_arg}").ordered }
71
+
72
+ it { target_instance.a_public_singleton_method dummy_arg }
73
+
74
+ end
75
+
76
+ context 'when protected method' do
77
+
78
+ context 'when calling protected method deliberately' do
79
+
80
+ it { expect{target_instance.a_protected_singleton_method dummy_arg}.to raise_error NoMethodError }
81
+
82
+ end
83
+
84
+ context 'when calling protected method through `send`' do
85
+
86
+ before { expect(target_instance).to receive(:puts).with(:a_decorated_protected_singleton_method).ordered }
87
+ before { expect(target_instance).to receive(:puts).with("a_protected_singleton_method_arg: #{dummy_arg}").ordered }
88
+
89
+ it { target_instance.send :a_protected_singleton_method, dummy_arg }
90
+
91
+ end
92
+
93
+ end
94
+
95
+ context 'when private method' do
96
+
97
+ context 'when calling private method deliberately' do
98
+
99
+ it { expect{target_instance.a_private_singleton_method dummy_arg}.to raise_error NoMethodError }
100
+
101
+ end
102
+
103
+ context 'when calling private method through `send`' do
104
+
105
+ before { expect(target_instance).to receive(:puts).with(:a_decorated_private_singleton_method).ordered }
106
+ before { expect(target_instance).to receive(:puts).with("a_private_singleton_method_arg: #{dummy_arg}").ordered }
107
+
108
+ it { target_instance.send :a_private_singleton_method, dummy_arg }
109
+
110
+ end
111
+
112
+ end
113
+
24
114
  end
25
115
 
26
116
  end
@@ -0,0 +1,69 @@
1
+ class DummyClass
2
+
3
+ def a_public_instance_method(arg)
4
+ puts "a_public_instance_method_arg: #{arg}"
5
+ end
6
+
7
+ protected
8
+
9
+ def a_protected_instance_method(arg)
10
+ puts "a_protected_instance_method_arg: #{arg}"
11
+ end
12
+
13
+ private
14
+
15
+ def a_private_instance_method(arg)
16
+ puts "a_private_instance_method_arg: #{arg}"
17
+ end
18
+
19
+ class << self
20
+
21
+ def a_public_singleton_method(arg)
22
+ puts "a_public_singleton_method_arg: #{arg}"
23
+ end
24
+
25
+ protected
26
+
27
+ def a_protected_singleton_method(arg)
28
+ puts "a_protected_singleton_method_arg: #{arg}"
29
+ end
30
+
31
+ private
32
+
33
+ def a_private_singleton_method(arg)
34
+ puts "a_private_singleton_method_arg: #{arg}"
35
+ end
36
+
37
+ end
38
+
39
+ end
40
+
41
+ MethodDecorator.decorate DummyClass, :a_public_instance_method do |*args, &block|
42
+ puts :a_decorated_public_instance_method
43
+ MethodDecorator.call_original_method self, :a_public_instance_method, *args, &block
44
+ end
45
+
46
+ MethodDecorator.decorate DummyClass, :a_protected_instance_method do |*args, &block|
47
+ puts :a_decorated_protected_instance_method
48
+ MethodDecorator.call_original_method self, :a_protected_instance_method, *args, &block
49
+ end
50
+
51
+ MethodDecorator.decorate DummyClass, :a_private_instance_method do |*args, &block|
52
+ puts :a_decorated_private_instance_method
53
+ MethodDecorator.call_original_method self, :a_private_instance_method, *args, &block
54
+ end
55
+
56
+ MethodDecorator.decorate DummyClass.singleton_class, :a_public_singleton_method do |*args, &block|
57
+ puts :a_decorated_public_singleton_method
58
+ MethodDecorator.call_original_method self, :a_public_singleton_method, *args, &block
59
+ end
60
+
61
+ MethodDecorator.decorate DummyClass.singleton_class, :a_protected_singleton_method do |*args, &block|
62
+ puts :a_decorated_protected_singleton_method
63
+ MethodDecorator.call_original_method self, :a_protected_singleton_method, *args, &block
64
+ end
65
+
66
+ MethodDecorator.decorate DummyClass.singleton_class, :a_private_singleton_method do |*args, &block|
67
+ puts :a_decorated_private_singleton_method
68
+ MethodDecorator.call_original_method self, :a_private_singleton_method, *args, &block
69
+ end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: method_decorator
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.0.0
4
+ version: 2.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - r4z3c
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2016-11-09 00:00:00.000000000 Z
11
+ date: 2017-02-21 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -87,7 +87,7 @@ files:
87
87
  - method_decorator.gemspec
88
88
  - spec/lib/method_decorator_spec.rb
89
89
  - spec/spec_helper.rb
90
- - spec/support/some_class.rb
90
+ - spec/support/dummy_class.rb
91
91
  homepage: https://github.com/r4z3c/method_decorator.git
92
92
  licenses:
93
93
  - MIT
@@ -115,4 +115,4 @@ summary: Overwrite methods preserving the original behavior
115
115
  test_files:
116
116
  - spec/lib/method_decorator_spec.rb
117
117
  - spec/spec_helper.rb
118
- - spec/support/some_class.rb
118
+ - spec/support/dummy_class.rb
@@ -1,22 +0,0 @@
1
- class SomeClass
2
-
3
- class << self
4
-
5
- def some_method(some_arg)
6
- puts some_arg
7
- end
8
-
9
- end
10
-
11
- def some_method(some_arg)
12
- puts some_arg
13
- end
14
-
15
- end
16
-
17
- [SomeClass, SomeClass.singleton_class].each do |target_class|
18
- MethodDecorator.decorate target_class, :some_method do |*args, &block|
19
- puts :decorated_some_method
20
- MethodDecorator.call_original self, :some_method, *args, &block
21
- end
22
- end