资源说明:Callbacks for your classes
h1. Aspectory h2. Callbacks for Ruby. h3. How it works Basically, you get three methods: @before@, @after@ and @around@. Each of these takes a method name, then a splat args of symbols and/or a block. The symbols/block will be called before/after the method you specified. The @around@ callback gets passed a proc, in the form of an unnamed block for handlers that are methods and a block argument for handlers that are blocks. You must @yield@ or @call@ that block in order for the original method to be called. h3. Simple Examplerequire 'rubygems' require 'aspectory' require 'spec' class Something include Aspectory::Hook attr_reader :results around :foo, :round before :foo, :setup after :foo, :teardown before :bar do @results << :before end around :bar do |fn| @results << :start fn.call @results << :finish end after :bar do @results << :after end def initialize @results = [] end def foo; @results << :foo; :foo end def bar; @results << :bar; :bar end def round @results << :start yield @results << :finish end def setup @results << :setup end def teardown @results << :teardown end end something = Something.new p something.foo # => :foo p something.results # => [:setup, :start, :foo, :finish, :teardown] something = Something.new p something.bar # => :bar p something.results # => [:before, :start, :bar, :finish, :after]something = Something.new something.foo # => :foo something.results # => [:setup, :foo, :teardown] something = Something.new something.bar # => :bar something.results # => [:before, :bar, :after]h3. Calling Methods without Callbacks You can use the @#__PRISTINE__@ method to call your methods without any callbacks, or you can just call @method_name_without_callbacks@. Here's an example with the same example class we used above:something = Something.new something.__PRISTINE__(:foo) something.results # => [:foo] something.bar_without_callbacks something.results # => [:foo, :bar]h3. Preventing a method from being called If a @before@ callback returns @false@, then the original method will not be called. If you want to halt the method being called, but still want to provide a return value, you can @throw@ the name of the method:class Something before :foo do throw :foo, "from the callback" end def foo "from the method" end end Something.new.foo # => "from the callback"h3. @after@ callbacks get the results of the method call Your @after@ callbacks will be passed whatever the original method call returned:class Something attr_reader :name after :foo do |result| @name = result.to_s.capitalize end def foo :foo end endsomething = Something.new something.name # => nil something.foo # => :foo something.name # => "Foo"h3. Observing method definitions If you ever want to see when a method is defined in a class, you can register observers using the @observe@ method. It can take either a symbol or a regular expression, then a callback block will be called when the method is defined. The callback block will be passed the name of the method defined. To observe class method definitions, you must pass the @:meta@ option.class Framework include Aspectory # Using a symbol observe :admin? do puts "Warning! Overriding the admin method can be dangerous." end # Using a regular expression observe(/^_/) do |method_id| puts "Warning! The #{method_id} is not part of the public API!" end # Observing a class method definition observe(:find_by_name, :meta => true) do puts "The method :find_by_name already exists in the framework." end # Observing multiple occurrences of a method definition observe(/^show_by_/, :times => true) do |method_id| puts "dynamic showing defined: #{method_id}" end endh3. Why? Why not? h3. Requirements * "nakajima":http://github.com/nakajima/nakajima @gem install nakajima-nakajima --source=http://gems.github.com@ h4. TODO * Filters (@:if@ and/or @:unless@) * Compilable callbacks ("http://gist.github.com/50397":http://gist.github.com/50397) * Maybe don't worry about @instance_eval@'ing or @instance_exec@'ing callback blocks. * Figure out a way to get it working with metaclasses * Spec suite could definitely be more readable h4. Alternatives: * http://github.com/sam/extlib/tree/master/lib/extlib/hook.rb * "AspectR":http://aspectr.sourceforge.net * "Aquarium":http://aquarium.rubyforge.org/ h4. "View the CI build":http://ci.patnakajima.com/booty-call @(c) Copyright 2008 Pat Nakajima, released under MIT License.@
本源码包内暂不包含可直接显示的源代码文件,请下载源码包。