A standard pattern to easily define and add behavior to a global behavior repository.
This pattern contains a macro that makes it easier to add such behaviors to Ruby classes of your choice.
The Behave pattern will be demonstrated by the troles gem for adding role behavior.
Behave also makes it easy to support multiple kinds of datastores via the schemaker gem,
that takes care of configuring your model relationships.
Behave::Config subject_class strategy orm (options) #configure! - applies the configuration to the subject class or module
The Behave::Config is the base class of a Behavior configuration?
User behaviors :trole Behave::Behavior name subject_class configuration_class -> Behave::Decorator::Configuration config -> Trole::Config instance < Behave::Config store -> Trole::Storage instance < Behave::Storage :troles => Behave::Behavior config -> Troles::Config instance < Behave::Config store -> Troles::Storage instance < Behave::Storage
Any module/class that can have behaviors, contains a hash ‘behaviors’ of named behaviors.
Each key in this hash points to a Behavior instance.
Behave::Repository registered_behaviors :trole Behave::Decorator configuration_class :troles Behave::Decorator configuration_class - inherits from module Behave::Decorator::Configuration strategy orm behavior config_class - Troles::Config < Behave::Config storage_class - Troles::Storage < Behave::Storage #load_adapter #setup_storage #setup_config
The Repository contains all the behaviors currently available to all modules and classes.
Note. In the following, the ‘subject’ is the module or class that is the target on which to apply the behavior.
First you must define your behavior and then register it to the singleton Behavior Repository like this:
Behave::Repository.register_behavior(:hello) do |behavior| behavior.configuration_class = MyBehavior::Configuration end
This is something you do for your Behavior “plugin”. This step has no relation to how it is used and configured on the subject.
After you have registered a behavior, you can apply it to various subjects (modules or classes) by using the #behavior macro, made available for any Module.
class User behavior(:trole_groups).configure_with :strategy => :ref_one do |config| strategy.orm = :mongoid strategy.auto_load = true end.configure! end
This will initially add a #behaviors collection to the subject class/module at the class level.
User behaviors :trole -> Behave::Behavior :troles -> Behave::Behavior ...
The #behaviors collection of the subject class is populated by instances of Behave::Behavior.
Each such behavior has a relationship to a Behave::Decorator instance with the same name, registered in the repository (registered_behaviors hash).
Behave::Repository registered_behaviors :trole -> Behave::Decorator
A Behave::Decorator instance has a Behave::Decorator::Configuration object that knows how to configure the behavior in a given context.
The Behave::Decorator::Configuration encapsulates concepts such as storage, strategy etc. and can do schema/model configuration (using schemaker).
Given strategy, ORM and some other options, the Behave::Decorator::Configuration instance will know how to load the right
data store adapter and find the right classes for storage, strategy etc. using specific loaders for each.
The Behave::Behavior instance will configure the subject using the Behave::Decorator#decorate method.
The result of the #behavior call is a Behave::Behavior object. If you call #configure_with on this Behavior object, you can configure how the behavior is to be applied to the subject.
The result of the #configure is a Behave::Config object, where you then lastly call #configure! to apply the configurations on the subject (late binding).
See the code for more details…
Note: This is currently work in progress… the above is subject to change!
Contributing to behave
- Check out the latest master to make sure the feature hasn’t been implemented or the bug hasn’t been fixed yet
- Check out the issue tracker to make sure someone already hasn’t requested it and/or contributed it
- Fork the project
- Start a feature/bugfix branch
- Commit and push until you are happy with your contribution
- Make sure to add tests for it. This is important so I don’t break it in a future version unintentionally.
- Please try not to mess with the Rakefile, version, or history. If you want to have your own version, or is otherwise necessary, that is fine, but please isolate to its own commit so I can cherry-pick around it.
Copyright © 2011 Kristian Mandrup. See LICENSE.txt for