Provides an interface for event hooks at any point during module include/extend or class subclassing.
Provides hooks via :included, :extended, :append_features, :extend_object, :inherited. Define behavior at hooks via simple interface.
- sudo gem install module-cluster
Extend the module that you want to enable:
module SomeModule extend Module::Cluster end
Hooks are defined on named clusters, that way they can be enabled/disabled later on.
There are four type of module hooks:
There are also subclass hooks:
Any of these hooks can be defined on a cluster:
module SomeModule # Create a hook to be activated before this module is included cluster( :some_cluster_name ).before_include end
Then declarations can be made by chaining calls.
module SomeModule cluster( :some_cluster_name ).before_include do |hooked_instance| # some stuff end end
The block passed to :before_include will be run when SomeModule is included in another module.
# Some other module we want to extend at include time module AnotherModule end module SomeModule cluster( :some_cluster_name ).before_include.extend( AnotherModule ) end
Now if SomeModule is included, the module in which it is included will also be extended by AnotherModule.
What if we only want to extend classes but not modules?
# Some other module we want to extend at include time module AnotherModule end module SomeModule cluster( :some_cluster_name ).before_include( :class ).extend( AnotherModule ) end
The same works for :any, :class, :module, :instance.
Sometimes we want to be able to declare that actions should happen well down the line. For instance, ModuleA should take action on the first class but might be included in any number of intermediate modules first. We can easily handle this case by declaring cascading behavior.
# Some other module we want to extend at include time module AnotherModule end module SomeModule cluster( :some_cluster_name ).before_include.cascade.extend( AnotherModule ) end
Now any module or class that includes SomeModule or any module or class that includes that module (and so on) will be extended by AnotherModule.
If we only want certain contexts to receive the cascading functionality we can limit it the same way we limited include/extend contexts:
# Some other module we want to extend at include time module AnotherModule end module SomeModule cluster( :some_cluster_name ).before_include.cascade_to( :class ).extend( AnotherModule ) end
:cascade_to is simply an alias to :cascade that is more readable when specifying contexts.
Now any module that includes SomeModule will cause the first class that includes it to be extended by AnotherModule.
Create a cluster to group together hooks. From the cluster declarations specify what context will cause event hooks to occur:
Any of these declarations will return a reference to aor a . Both have the same interface, so you don't need to worry about the difference.
From the reference returned by a hook context the following declarations can be made:
Hook Action Contexts
As we have shown, declarations to cause cascading behavior can also be made here:
Also, contexts can be set so that hook order can be easily manipulated. This will cause hook events to be inserted in the stack other than at the end:
All of these possibilities returns a reference where hook actions can be defined, exactly the same as above. The only difference is that they will occur in the chained context, which is the context described by the chained declarations. Any time that declarations begin again from the cluster, chained declarations will reset.
(The MIT License)
Copyright (c) 2012 Ridiculous Power, Asher
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the 'Software'), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.