Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Assorted fixes.

  * A method advised with after now returns its value, and not after's.
  * We now detect bad arguments passed to before/after.
  * Methods ending in = can now be advised.
  • Loading branch information...
commit d38e4e95a17a0f0585b5568700cc16f510449fbc 1 parent 57ef165
David Leal authored
Showing with 69 additions and 10 deletions.
  1. +12 −6 lib/data_mapper/hook.rb
  2. +57 −4 spec/unit/hook_spec.rb
18 lib/data_mapper/hook.rb
View
@@ -8,8 +8,16 @@ module ClassMethods
def before(target_method, method_sym = nil, &block)
install_hook :before, target_method, method_sym, &block
end
+
+ def after(target_method, method_sym = nil, &block)
+ install_hook :after, target_method, method_sym, &block
+ end
def install_hook(type, name, method_sym = nil, &block)
+ raise ArgumentError.new("You need to pass 2 arguments to \"#{type}\".") if ! block_given? and method_sym.nil?
+ raise ArgumentError.new("target_method should be a symbol") unless name.is_a?(Symbol)
+ raise ArgumentError.new("method_sym should be a symbol") if method_sym && ! method_sym.is_a?(Symbol)
+
(hooks[name][type] ||= []) << if block
new_meth_name = "__hooks_#{type}_#{quote_method(name)}_#{hooks[name][type].length}".to_sym
define_method new_meth_name, block
@@ -21,14 +29,16 @@ def install_hook(type, name, method_sym = nil, &block)
class_eval define_advised_method(name), __FILE__, __LINE__
end
+ # FIXME Return the method value
def define_advised_method(name)
args = args_for(hooks[name][:old_method] ||= instance_method(name))
<<-EOD
def #{name}(#{args})
#{inline_hooks(name, :before, args)}
- #{inline_call(name, args)}
+ retval = #{inline_call(name, args)}
#{inline_hooks(name, :after, args)}
+ retval
end
EOD
end
@@ -80,11 +90,7 @@ def hooks
end
def quote_method(name)
- name.to_s.gsub(/\?$/, '_q_').gsub(/!$/, '_b_')
- end
-
- def after(target_method, method_sym = nil, &block)
- install_hook :after, target_method, method_sym, &block
+ name.to_s.gsub(/\?$/, '_q_').gsub(/!$/, '_b_').gsub(/=$/, '_eq_')
end
end
end # module Hook
61 spec/unit/hook_spec.rb
View
@@ -185,7 +185,22 @@ def a_hook
end
@class.new.a_method
- end end
+ end
+
+ it "the advised method should still return its normal value" do
+ @class.class_eval do
+ def returner
+ 1
+ end
+
+ after :returner do
+ 2
+ end
+ end
+
+ @class.new.returner.should == 1
+ end
+ end
it 'should allow the use of before and after together' do
tester = mock("tester")
@@ -239,10 +254,12 @@ def a_hook
@class.new.a_method?
end
- it "should allow advising methods ending in ? or ! when passing methods as advices" do
+ it "should allow advising methods ending in ?, ! or = when passing methods as advices" do
tester = mock("tester")
- tester.should_receive(:before).ordered.once
+ tester.should_receive(:before_bang).ordered.once
tester.should_receive(:method!).ordered.once
+ tester.should_receive(:before_eq).ordered.once
+ tester.should_receive(:method_eq).ordered.once
tester.should_receive(:method?).ordered.once
tester.should_receive(:after).ordered.once
@@ -255,12 +272,22 @@ def a_hook
tester.method?
end
+ define_method :a_method= do |value|
+ tester.method_eq
+ end
+
define_method :before_a_method_bang do
- tester.before
+ tester.before_bang
end
before :a_method!, :before_a_method_bang
+ define_method :before_a_method_eq do
+ tester.before_eq
+ end
+
+ before :a_method=, :before_a_method_eq
+
define_method :after_a_method_question do
tester.after
end
@@ -269,6 +296,32 @@ def a_hook
end
@class.new.a_method!
+ @class.new.a_method = 1
@class.new.a_method?
end
+
+ it "should complain when only one argument is passed" do
+ lambda do
+ @class.class_eval do
+ before :a_method
+ after :a_method
+ end
+ end.should raise_error(ArgumentError)
+ end
+
+ it "should complain when target_method is not a symbol" do
+ lambda do
+ @class.class_eval do
+ before "target", :something
+ end
+ end.should raise_error(ArgumentError)
+ end
+
+ it "should complain when method_sym is not a symbol" do
+ lambda do
+ @class.class_eval do
+ before :target, "something"
+ end
+ end.should raise_error(ArgumentError)
+ end
end
Please sign in to comment.
Something went wrong with that request. Please try again.