method_wrapper 0.1.1 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
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