Mention AroundDecorator in README.txt.
[decorate.git] / lib / decorate / before_decorator.rb
blob455f0d44d000454a763321f7b083a46af2cbd09c
1 require "decorate"
2 require "decorate/create_alias"
4 # This module is highly experimental and might change significantly or
5 # be removed completely since its usefulness is highly questionable in
6 # its current form.
7 module Decorate::BeforeDecorator
9   # Example:
10   #
11   #   require "decorate/before_decorator"
12   #
13   #   class Bf
14   #     extend Decorate::BeforeDecorator
15   #
16   #     before_decorator :trace_call, :call => :trace_call
17   #
18   #     def trace_call(method_name, *args, &block)
19   #       puts "Before #{self}.#{method_name}, args: #{args.inspect}, block: #{block.inspect}"
20   #     end
21   #
22   #     def foo
23   #       puts "foo"
24   #     end
25   #
26   #     trace_call
27   #     def bar
28   #       puts "bar"
29   #     end
30   #
31   #   end
32   #
33   #   >> o = Bf.new
34   #   >> o.foo
35   #   foo
36   #   >> o.bar
37   #   Before #<Bf:0xb7b32dbc>.bar, args: [], block: nil
38   #   bar
39   def before_decorator(decorator_name, opts) #:doc:
40     before_method_name = opts[:call]
41     unless before_method_name.kind_of?(Symbol)
42       raise "Option :call with Symbol argument required"
43     end
44     unkown_opt = opts.keys.find { |opt| ![:call].include?(opt) }
45     if unkown_opt
46       raise "Unknown option #{unknown_opt.inspect}"
47     end
49     self.class.send(:define_method, decorator_name) {
50       Decorate.decorate { |klass, method_name|
51         wrapped_method_name =
52           Decorate.create_alias(klass, method_name, decorator_name)
53         klass.class_eval <<-EOF, __FILE__, __LINE__
54           def #{method_name}(*args, &block)
55             self.__send__(:#{before_method_name},
56                           :#{method_name}, *args, &block)
57             self.__send__(:#{wrapped_method_name},
58                           *args, &block)
59           end
60         EOF
61       }
62     }
63   end
64   private :before_decorator
66 end