method_wrapper 0.1.1 → 0.2.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.
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- method_wrapper (0.1.1)
4
+ method_wrapper (0.2.0)
5
5
 
6
6
  GEM
7
7
  remote: http://rubygems.org/
@@ -25,4 +25,3 @@ DEPENDENCIES
25
25
  bundler (>= 1.0.0.rc.5)
26
26
  method_wrapper!
27
27
  rspec (>= 2.0.0)
28
-
data/README.rdoc CHANGED
@@ -4,71 +4,60 @@
4
4
 
5
5
  == Introduction
6
6
 
7
- This gem helps you to wrap new features around (before and after) existing methods call on any classes.
8
-
9
- The before_ and after_ callbacks will run as soon as you call wrapped method.
7
+ alias_method_chain alternative. How easy to wrap new features around existing methods with method_wrapper.
10
8
 
11
9
  == Installation
12
10
 
13
11
  gem install method_wrapper
14
12
 
15
13
  == Examples
16
- require 'method_wrapper'
17
-
18
- class Klass
19
- include MethodWrapper
20
- wrap_methods :method_name
21
-
22
- def method_name
23
- puts 'hi'
24
- end
25
-
26
- def before_method_name
27
- puts "calls before method name"
28
- end
29
14
 
30
- def after_method_name
31
- puts "calls after method name"
32
- end
33
- end
34
-
35
- You can also has partial callback
15
+ * Wrap multi methods to a feature in a line.
16
+ * Be able to call wrap_methods before methods defined.
36
17
  require 'method_wrapper'
18
+ * Call original method(origin_method_name). Note: I take different style from alias_method_chain because we don't want users to know what feature has been wrapped.
19
+
20
+ == Examples
37
21
 
38
22
  class Klass
39
23
  include MethodWrapper
40
- wrap_methods :method_name, :second_method_name
24
+ wrap_methods [:save!, :query] => :log
41
25
 
42
- def method_name
43
- puts 'hi'
26
+ def save!
27
+ "save"
44
28
  end
45
29
 
46
- def second_method_name
47
- puts 'hello'
30
+ def query
31
+ "update"
48
32
  end
49
33
 
50
- def before_method_name
51
- puts "calls before method name"
34
+ def save_with_log!
35
+ origin_save! + " with log"
52
36
  end
53
37
 
54
- def after_method_name
55
- puts "calls after method name"
56
- end
57
-
58
- def after_second_method_name
59
- puts "calls after second method name"
38
+ def query_with_log
39
+ origin_query! + " with log"
60
40
  end
61
41
  end
62
42
 
63
- You can also open the existing classes to wrap methods
43
+ obj = Klass.new
44
+ obj.save!
45
+ => "save with log"
46
+ obj.origin_save!
47
+ => "save"
48
+
49
+ You can also open the existing classes to wrap methods. Note: Be careful, you know what you are doing.
64
50
  require 'method_wrapper'
65
51
 
66
52
  class String
67
53
  include MethodWrapper
68
- wrap_methods :reverse
54
+ wrap_methods :reverse => :upcase
69
55
 
70
- def before_reverse
71
- puts "calls before string reverse"
56
+ def reverse_with_upcase
57
+ origin_reverse.upcase
72
58
  end
73
59
  end
74
60
 
61
+ "nuhhc gnanmas".reverse
62
+ => SAMNANG CHHUN
63
+
@@ -1,51 +1,88 @@
1
1
  module MethodWrapper
2
2
  def self.included(base)
3
- base.instance_variable_set(:@_wrapped_methods, [])
3
+ base.instance_variable_set(:@__wrapped_methods, {})
4
4
  base.extend ClassMethods
5
5
  end
6
6
 
7
- private
8
- def invoke_method(name)
9
- send(name) if respond_to? name, true
10
- end
11
-
12
7
  module ClassMethods
8
+ def wrap_methods(params)
9
+ method_names, feature = params.first
10
+ method_names = [method_names] unless method_names.instance_of? Array
11
+
12
+ method_names.each do |name|
13
+ feature_name = feature_method_name(name, feature)
14
+ @__wrapped_methods[name] = feature_name
15
+
16
+ __wrap_method!(name, feature_name)
17
+ end
18
+ end
19
+
13
20
  def method_added(name)
14
- return if @_disable_hook_method_added
21
+ return if @disable_method_added_hook
15
22
 
16
- _wrap_method!(name) if @_wrapped_methods.include? name
23
+ new_added_method_has_in_wrpped_methods(name)
17
24
  end
18
25
 
19
- def wrap_methods(*args)
20
- @_wrapped_methods = args
26
+ def include(*modules)
27
+ super
21
28
 
22
- @_wrapped_methods.each do |name|
23
- _wrap_method!(name) if instance_method_defined? name
29
+ @__wrapped_methods.each do |k, v|
30
+ __wrap_method!(k, v)
24
31
  end
25
32
  end
26
33
 
27
34
  private
28
- def _wrap_method!(name)
29
- @_disable_hook_method_added = true
35
+ def __wrap_method!(name, feature_name)
36
+ return unless methods_have_already_defined?(name, feature_name)
37
+
38
+ origin_name = origin_method_name(name)
30
39
 
31
- origin_method_name = "origin_#{name}"
32
- origin_method = instance_method(name)
40
+ @disable_method_added_hook = true
33
41
 
34
- alias_method origin_method_name, name
42
+ alias_method origin_name, name
43
+ alias_method name, feature_name
35
44
 
36
- define_method(name) do |*args, &block|
37
- invoke_method("before_#{name}")
38
- return_result = origin_method.bind(self).call(*args, &block)
39
- invoke_method("after_#{name}")
45
+ @disable_method_added_hook = false
40
46
 
41
- return_result
47
+ [:public, :protected, :private].each do |v|
48
+ send(v, name) if send("#{v}_method_defined?", origin_name)
42
49
  end
50
+ end
51
+
52
+ def feature_method_name(name, feature)
53
+ name = name.to_s
54
+ feature_name = name.end_with?("!", "?", "=") ?
55
+ "#{name[0..-2]}_with_#{feature}#{name[-1]}" :
56
+ "#{name}_with_#{feature}"
43
57
 
44
- @_disable_hook_method_added = false
58
+ feature_name.to_sym
45
59
  end
46
60
 
47
- def instance_method_defined?(name)
48
- instance_methods.include? name.to_sym
61
+ def origin_method_name(name)
62
+ "origin_#{name}"
63
+ end
64
+
65
+
66
+ def methods_have_already_defined?(*args)
67
+ args.each {|name| return false unless all_instance_methods.include? name }
68
+
69
+ true
70
+ end
71
+
72
+ def all_instance_methods
73
+ public_instance_methods +
74
+ protected_instance_methods +
75
+ private_instance_methods
76
+ end
77
+
78
+ def new_added_method_has_in_wrpped_methods(name)
79
+ if @__wrapped_methods.has_key? name
80
+ feature_name = @__wrapped_methods[name]
81
+ __wrap_method!(name, feature_name)
82
+ elsif @__wrapped_methods.has_value? name
83
+ name, feature_name = @__wrapped_methods.select{|k, v| v == name }.first
84
+ __wrap_method!(name, feature_name)
85
+ end
49
86
  end
50
87
  end
51
88
  end
@@ -1,4 +1,4 @@
1
1
  module MethodWrapper
2
- VERSION = "0.1.1"
2
+ VERSION = "0.2.0"
3
3
  end
4
4
 
@@ -9,8 +9,8 @@ Gem::Specification.new do |s|
9
9
  s.authors = ["Samnang Chhun"]
10
10
  s.email = ["samnang.chhun@gmail.com"]
11
11
  s.homepage = "http://github.com/samnang/method_wrapper"
12
- s.summary = "How easy to wrap new features around (before and after) existing methods call with method_wrapper."
13
- s.description = "This gem helps you to wrap new features around (before and after) existing methods call on any classes. The before_ and after_ callbacks will run as soon as you call wrapped method."
12
+ s.summary = "Alternative alias_method_chain. How easy to wrap new features around existing methods with method_wrapper."
13
+ s.description = "alias_method_chain alternative. How easy to wrap new features around existing methods with method_wrapper."
14
14
 
15
15
  s.required_rubygems_version = ">= 1.3.6"
16
16
  s.rubyforge_project = "[none]"
@@ -1,81 +1,40 @@
1
1
  class ClassBuilder
2
2
  class << self
3
- def a_class_has_methods_and_calls_after_methods_defined
4
- Class.new do
5
- include MethodWrapper
6
-
7
- def method_name
8
- end
9
-
10
- def second_method_name
11
- end
12
-
13
- wrap_methods :method_name, :second_method_name
14
- end
15
- end
16
-
17
- def a_class_has_methods_and_calls_before_methods_defined
18
- Class.new do
19
- include MethodWrapper
20
- wrap_methods :method_name, :second_method_name
3
+ module Methods
4
+ def name!; end
5
+ def name1; end
21
6
 
22
- def method_name
23
- end
7
+ def name_with_feature!; end
8
+ def name1_with_feature; end
24
9
 
25
- def second_method_name
26
- end
27
- end
10
+ private :name1
28
11
  end
29
12
 
30
- def a_class_has_before_and_after_wrap_methods
13
+ def a_class_with_2_methods_add_feature
31
14
  Class.new do
32
15
  include MethodWrapper
33
- wrap_methods :method_name
34
-
35
- def method_name
36
- end
16
+ include Methods
37
17
 
38
- private
39
- def before_method_name
40
- @has_called_before_callback = true
41
- end
42
-
43
- def after_method_name
44
- @has_called_after_callback = true
45
- end
18
+ wrap_methods :name! => :feature
19
+ wrap_methods :name1 => :feature
46
20
  end
47
21
  end
48
22
 
49
- def a_class_has_partial_callback
23
+ def a_class_calls_wrap_methods_with_array_of_methods
50
24
  Class.new do
51
25
  include MethodWrapper
26
+ include Methods
52
27
 
53
- def method_name
54
- end
55
-
56
- private
57
- def before_method_name
58
- @has_called_before_callback = true
59
- end
60
-
61
- wrap_methods :method_name
28
+ wrap_methods [:name!, :name1] => :feature
62
29
  end
63
30
  end
64
31
 
65
- def a_class_has_method_with_args_and_block
32
+ def a_class_calls_wrap_methods_before_methods_defined
66
33
  Class.new do
67
34
  include MethodWrapper
68
- wrap_methods :method_name
69
-
70
- def method_name(param)
71
- @param = param
72
- yield
73
- end
35
+ wrap_methods [:name!, :name1] => :feature
74
36
 
75
- private
76
- def after_method_name
77
- @has_called_after_callback = true
78
- end
37
+ include Methods
79
38
  end
80
39
  end
81
40
  end
@@ -1,57 +1,46 @@
1
1
  require 'spec_helper'
2
2
 
3
3
  describe MethodWrapper do
4
- describe ".wrap_methods, stores methods that want to wrap" do
5
- it "calls after method defined" do
6
- klass = ClassBuilder.a_class_has_methods_and_calls_after_methods_defined
4
+ describe ".wrap_methods" do
5
+ let(:klass) { klass = ClassBuilder.a_class_with_2_methods_add_feature }
7
6
 
7
+ it "should stores the wrapped methods with feature" do
8
8
  verify_wrapped_methods(klass)
9
9
  end
10
10
 
11
- it "calls before method defined" do
12
- klass = ClassBuilder.a_class_has_methods_and_calls_before_methods_defined
11
+ it "should be able call wrap_methods with array of method" do
12
+ klass = ClassBuilder.a_class_calls_wrap_methods_with_array_of_methods
13
13
 
14
14
  verify_wrapped_methods(klass)
15
15
  end
16
16
 
17
- def verify_wrapped_methods(klass)
18
- klass.instance_variable_get(:@_wrapped_methods).should ==
19
- [:method_name, :second_method_name]
17
+ it "should wrap new feature to methods" do
18
+ verify_alias_methods(klass)
20
19
  end
21
- end
22
-
23
- context "invoke the wrapped methods" do
24
- it "should invoke _before_method_name and after_method_name" do
25
- klass = ClassBuilder.a_class_has_before_and_after_wrap_methods
26
- obj = klass.new
27
-
28
- obj.method_name
29
20
 
30
- obj.instance_variable_get(:@has_called_before_callback).should eql(true)
31
- obj.instance_variable_get(:@has_called_after_callback).should eql(true)
21
+ it "should create new method for origin method" do
22
+ klass.new.should be_respond_to :origin_name!
23
+ klass.new.should be_respond_to :origin_name1, true #include private
32
24
  end
33
25
 
34
- it "should ignore callbacks if user hasn't defined" do
35
- klass = ClassBuilder.a_class_has_partial_callback
36
- obj = klass.new
26
+ it "should restore visibility to origin method" do
27
+ klass.private_instance_methods.should include(:name1)
28
+ end
37
29
 
38
- obj.method_name
30
+ it "should be able to calls before methods defined" do
31
+ klass = ClassBuilder.a_class_calls_wrap_methods_before_methods_defined
39
32
 
40
- obj.instance_variable_get(:@has_called_before_callback).should eql(true)
33
+ verify_alias_methods(klass)
41
34
  end
42
35
 
43
- it "should be able to invoke the method with args and block" do
44
- klass = ClassBuilder.a_class_has_method_with_args_and_block
45
- obj = klass.new
46
- has_called = false
47
-
48
- obj.method_name("value") do
49
- has_called = true
50
- end
36
+ def verify_wrapped_methods(klass)
37
+ klass.instance_variable_get(:@__wrapped_methods).should ==
38
+ {:name! => :name_with_feature!, :name1 => :name1_with_feature}
39
+ end
51
40
 
52
- obj.instance_variable_get(:@param).should eql("value")
53
- has_called.should eql(true)
54
- obj.instance_variable_get(:@has_called_after_callback).should eql(true)
41
+ def verify_alias_methods(klass)
42
+ klass.should has_alias_method(:name!, :name_with_feature!)
43
+ klass.should has_alias_method(:name1, :name1_with_feature)
55
44
  end
56
45
  end
57
46
  end
data/spec/spec_helper.rb CHANGED
@@ -3,3 +3,9 @@ require 'rspec'
3
3
  require_relative 'class_builder'
4
4
  require_relative '../lib/method_wrapper.rb'
5
5
 
6
+ RSpec::Matchers.define :has_alias_method do |first, second|
7
+ match do |klass|
8
+ klass.instance_method(first).should == klass.instance_method(second)
9
+ end
10
+ end
11
+
metadata CHANGED
@@ -4,9 +4,9 @@ version: !ruby/object:Gem::Version
4
4
  prerelease: false
5
5
  segments:
6
6
  - 0
7
- - 1
8
- - 1
9
- version: 0.1.1
7
+ - 2
8
+ - 0
9
+ version: 0.2.0
10
10
  platform: ruby
11
11
  authors:
12
12
  - Samnang Chhun
@@ -14,7 +14,7 @@ autorequire:
14
14
  bindir: bin
15
15
  cert_chain: []
16
16
 
17
- date: 2010-10-30 00:00:00 +07:00
17
+ date: 2010-11-01 00:00:00 +07:00
18
18
  default_executable:
19
19
  dependencies:
20
20
  - !ruby/object:Gem::Dependency
@@ -49,7 +49,7 @@ dependencies:
49
49
  version: 2.0.0
50
50
  type: :development
51
51
  version_requirements: *id002
52
- description: This gem helps you to wrap new features around (before and after) existing methods call on any classes. The before_ and after_ callbacks will run as soon as you call wrapped method.
52
+ description: alias_method_chain alternative. How easy to wrap new features around existing methods with method_wrapper.
53
53
  email:
54
54
  - samnang.chhun@gmail.com
55
55
  executables: []
@@ -103,6 +103,6 @@ rubyforge_project: "[none]"
103
103
  rubygems_version: 1.3.7
104
104
  signing_key:
105
105
  specification_version: 3
106
- summary: How easy to wrap new features around (before and after) existing methods call with method_wrapper.
106
+ summary: Alternative alias_method_chain. How easy to wrap new features around existing methods with method_wrapper.
107
107
  test_files: []
108
108