lib/surrounded/context.rb in surrounded-0.8.4 vs lib/surrounded/context.rb in surrounded-0.9.0
- old
+ new
@@ -1,9 +1,10 @@
require 'set'
require 'surrounded/context/role_map'
require 'surrounded/context/role_builders'
require 'surrounded/context/initializing'
+require 'surrounded/context/trigger_controls'
require 'surrounded/access_control'
require 'surrounded/shortcuts'
require 'surrounded/east_oriented'
# Extend your classes with Surrounded::Context to handle their
@@ -13,133 +14,62 @@
# The purpose of this module is to help you create context objects
# which encapsulate the interaction and behavior of objects inside.
module Surrounded
module Context
def self.extended(base)
- base.extend RoleBuilders, Initializing
base.class_eval {
+ extend RoleBuilders, Initializing
+
@triggers = Set.new
include InstanceMethods
+
+ trigger_mod = Module.new
+ const_set('TriggerMethods', trigger_mod)
+ include trigger_mod
+
+ extend TriggerControls
}
end
- # Provides a Set of all available trigger methods where
- # behaviors will be applied to the roles before execution
- # and removed afterward.
- def triggers
- @triggers.dup
- end
-
private
# Set the default type of implementation for role methods for all contexts.
def self.default_role_type
@default_role_type ||= :module
end
class << self
attr_writer :default_role_type
end
-
- # Provide the ability to create access control methods for your triggers.
- def protect_triggers; self.extend(::Surrounded::AccessControl); end
-
- # Automatically create class methods for each trigger method.
- def shortcut_triggers; self.extend(::Surrounded::Shortcuts); end
-
- # Automatically return the context object from trigger methods.
- def east_oriented_triggers; self.extend(::Surrounded::EastOriented); end
def default_role_type
@default_role_type ||= Surrounded::Context.default_role_type
end
# Set the default type of implementation for role method for an individual context.
def default_role_type=(type)
@default_role_type = type
end
+
+ # Provide the ability to create access control methods for your triggers.
+ def protect_triggers; self.extend(::Surrounded::AccessControl); end
- # Set the time to apply roles to objects. Either :trigger or :initialize.
- # Defaults to :trigger
- def apply_roles_on(which)
- @__apply_role_policy = which
- end
+ # Automatically create class methods for each trigger method.
+ def shortcut_triggers; self.extend(::Surrounded::Shortcuts); end
- def __apply_role_policy
- @__apply_role_policy ||= :trigger
- end
+ # Automatically return the context object from trigger methods.
+ def east_oriented_triggers; self.extend(::Surrounded::EastOriented); end
- # Creates a context instance method which will apply behaviors to role players
- # before execution and remove the behaviors after execution.
- #
- # Alternatively you may define your own methods then declare them as triggers
- # afterward.
- #
- # Example:
- # trigger :some_event do
- # # code here
- # end
- #
- # def some_event
- # # code here
- # end
- # trigger :some_event
- #
- def trigger(*names, &block)
- if block.nil?
- names.each do |name|
- convert_method_to_trigger(name)
- end
- else
- name = names.first
- define_method(name, &block)
- convert_method_to_trigger(name)
- end
- end
+ # === Utility shortcuts
- def store_trigger(*names)
- @triggers.merge(names)
+ def role_const_defined?(name)
+ const_defined?(name, false)
end
- def convert_method_to_trigger(name)
- unless triggers.include?(name) || name.nil?
- alias_method :"__trigger_#{name}", :"#{name}"
- private :"__trigger_#{name}"
- remove_method :"#{name}"
- define_trigger_wrap_method(name)
- store_trigger(name)
- end
- end
-
- def define_trigger_wrap_method(name)
- mod = Module.new
- line = __LINE__
- mod.class_eval %{
- def #{name}(*args, &block)
- begin
- apply_roles if __apply_role_policy == :trigger
-
- #{trigger_return_content(name)}
-
- ensure
- remove_roles if __apply_role_policy == :trigger
- end
- end
- }, __FILE__, line
- const_set("SurroundedTrigger#{name.to_s.upcase.sub(/\?\z/,'Query')}", mod)
- include mod
- end
-
- def trigger_return_content(name, *args, &block)
- %{self.send("__trigger_#{name}", *args, &block)}
- end
-
- # === Utility shortcuts
-
# Set a named constant and make it private
def private_const_set(name, const)
- unless self.const_defined?(name, false)
+ unless role_const_defined?(name)
const = const_set(name, const)
private_constant name.to_sym
end
const
end
@@ -155,14 +85,10 @@
if role_const_defined?(name)
const_get(name)
end
end
- def role_const_defined?(name)
- const_defined?(name, false)
- end
-
module InstanceMethods
# Check whether a given name is a role inside the context.
# The provided block is used to evaluate whether or not the caller
# is allowed to inquire about the roles.
def role?(name, &block)
@@ -181,18 +107,10 @@
self.class.triggers
end
private
- def preinitialize
- @__apply_role_policy = self.class.send(:__apply_role_policy)
- end
-
- def postinitialize
- apply_roles if __apply_role_policy == :initialize
- end
-
def role_map
@role_map ||= RoleMap.new
end
def map_roles(role_object_array)
@@ -219,62 +137,68 @@
def map_role(role, mod_name, object)
instance_variable_set("@#{role}", object)
role_map.update(role, role_module_basename(mod_name), object)
end
- def __apply_role_policy
- @__apply_role_policy
- end
-
- def add_interface(role, behavior, object)
+ def apply_behavior(role, behavior, object)
if behavior && role_const_defined?(behavior)
- applicator = role_const(behavior).is_a?(Class) ? method(:add_class_interface) : method(:add_module_interface)
+ applicator = if self.respond_to?("apply_behavior_#{role}")
+ method("apply_behavior_#{role}")
+ elsif role_const(behavior).is_a?(Class)
+ method(:apply_class_behavior)
+ else
+ method(:apply_module_behavior)
+ end
- role_player = applicator.call(object, role_const(behavior))
+ role_player = applicator.call(role_const(behavior), object)
map_role(role, behavior, role_player)
end
role_player || object
end
- def add_module_interface(obj, mod)
+ def apply_module_behavior(mod, obj)
adder_name = module_extension_methods.find{|meth| obj.respond_to?(meth) }
- return obj if !adder_name
+ return obj unless adder_name
obj.method(adder_name).call(mod)
obj
end
- def add_class_interface(obj, klass)
+ def apply_class_behavior(klass, obj)
wrapper_name = wrap_methods.find{|meth| klass.respond_to?(meth) }
return obj if !wrapper_name
klass.method(wrapper_name).call(obj)
end
-
- def remove_interface(role, behavior, object)
+
+ def remove_behavior(role, behavior, object)
if behavior && role_const_defined?(behavior)
- remover_name = (module_removal_methods + unwrap_methods).find{|meth| object.respond_to?(meth) }
+ remover_name = (module_removal_methods + unwrap_methods).find do |meth|
+ object.respond_to?(meth)
+ end
end
- if remover_name
- role_player = object.send(remover_name)
- end
+ role_player = if self.respond_to?("remove_behavior_#{role}")
+ self.send("remove_behavior_#{role}", role_const(behavior), object)
+ elsif remover_name
+ object.send(remover_name)
+ end
role_player || object
end
- def apply_roles
+ def apply_behaviors
role_map.each do |role, mod_name, object|
- player = add_interface(role, mod_name, object)
+ player = apply_behavior(role, mod_name, object)
player.send(:store_context, self) do; end
end
end
- def remove_roles
+ def remove_behaviors
role_map.each do |role, mod_name, player|
if player.respond_to?(:remove_context, true)
player.send(:remove_context) do; end
end
- remove_interface(role, mod_name, player)
+ remove_behavior(role, mod_name, player)
end
end
# List of possible methods to use to add behavior to an object from a module.
def module_extension_methods
\ No newline at end of file