Skip to content
gcao edited this page Oct 23, 2011 · 11 revisions

Usage

require 'aspect4r'

Add 'include Aspect4r' to class or module where advices will be defined.

API

When Aspect4r is included, four singleton methods are available for defining advices on target class/module: before, before_filter, after, around. They have same method signature below and process arguments similarly.

advice_type(methods, options={}, &advice_block)

methods: a list of methods that will be advised. If no block is given, then the last method contains the advice logic and is applied to other methods. For example, before :test1, :test2, :do_something means run do_something before test1 and test2.

options [optional]: Each type of advice can potentially take options only applicable to that type. Those options will be covered later in this document. All advices can take method_name_arg and name option. If method_name_arg is true, then the advice method or block's first argument is the target method name so that advice logic can be customized for different methods, e.g.

before :test1, :test2, :method_name_arg => true do |method, *args|
  if method == 'test1'
  else
  end
end

advice_block [optional]: contains advice logic. If it is missing, methods should contain at least 2 methods, last one contains the advice logic.

before(methods, options={}, &advice_block)

Define an advice which runs before target methods. Currently there is no special option can be used for this type of device.

Normally, before advice will not halt execution of advices defined later and the wrapped method. However, there is a special wrapper class Aspect4r::ReturnThis. When the result of a before advice is an instance of ReturnThis, execution will stop and the result wrapped inside will be returned, e.g.

before :test do |input|
  return Aspect4r::ReturnThis.new('default') if input.nil?
end
instance.test(nil)   # => 'default'

before_filter(methods, options={}, &advice_block)

Define an advice which runs before target methods and if this advice returns false or nil, execution will halt. This is a special case of before advice. Currently there is no special option can be used for this type of device. Example:

before_filter :test do |input|
  input >= 0
end

after(methods, options={}, &advice_block)

Define an advice which runs after target methods. After advice can take a result_arg option which is set to true by default. When it is true, the result of wrapped method or previous after advice is passed as the first argument to the advice, also the result of the after advice will be used as the method result. When result_arg is set to false, result will not be passed into advice method, and the advice result will not be used as the method result. Example

after :test do |result, input|
  "<em>#{result}</em>"       # => new result
end
after :test, :result_arg => false do |input|
  cleanup                    # will not change what test will return
end

around(methods, options={}, &advice_block)

Define an advice which runs around target methods. A block that represents the wrapped method (and advices if any) is passed to the advice method or block. The advice logic can decide whether and when the block is called. Currently there is no special option can be used for this type of advice. Example:

around :test do |input, &block|
  return if input.nil?

  result = block.call input
  result.upcase
end

Aspect4r::Classic

Because before, before_filter and after are common method names used by several Ruby libraries/frameworks (e.g. Rails, RSpec), to avoid collision, Aspect4r provides a different set of methods (a4r_before, a4r_before_filter, a4r_after, a4r_around) with same functionalities. Here is how you use those instead.

class A
  include Aspect4r::Classic
  a4r_before :test do
  end
  a4r_after :test do
  end
end