README.md in surrounded-0.9.5 vs README.md in surrounded-0.9.6

- old
+ new

@@ -551,54 +551,54 @@ # this uses a special interface object which pulls # methods from a module and applies them to your object. role :source, :interface do def transfer self.balance -= amount - # not able to access destination - # destination.balance += amount + # not able to access destination unless the object playing source is Surrounded + destination.balance += amount self end end ``` The `:interface` option is a special object which has all of the standard Object methods removed (excepting ones like `__send__` and `object_id`) so that other methods will be pulled from the ones that you define, or from the object it attempts to proxy. Notice that the `:interface` allows you to return `self` whereas the `:wrap` acts more like a wrapper and forces you to deal with that shortcoming by using it's wrapped-object-accessor method: `__getobj__`. -The downside of using an interface is that it is still a wrapper and it doesn't have access to the other objects in the context. All of your defined role methods are executed in the context of the object playing the role, but the interface has it's own identity. +The downside of using an interface is that it is still a wrapper and it only has access to the other objects in the context if the wrapped object already includes Surrounded. All of your defined role methods are executed in the context of the object playing the role, but the interface has it's own identity. If you'd like to choose one and use it all the time, you can set the default: ```ruby class MoneyTransfer extend Surrounded::Context - self.default_role_type = :wrapper # also :wrap, :interface, or :module + self.default_role_type = :interface # also :wrap, :wrapper, or :module role :source do def transfer self.balance -= amount destination.balance += amount - __getobj__ + self end end end ``` Or, if you like, you can choose the default for your entire project: ```ruby -Surrounded::Context.default_role_type = :wrap +Surrounded::Context.default_role_type = :interface class MoneyTransfer extend Surrounded::Context role :source do def transfer self.balance -= amount destination.balance += amount - __getobj__ + self end end end ``` @@ -612,11 +612,13 @@ be given the behaviors from a `Members` behavior module or class. Each item in your `members` collection would be given behavior from a `Member` behavior module or class if you create one. ```ruby class Organization - initialize :leader, :members + extend Surrounded::Context + + initialize_without_keywords :leader, :members role :members do # special behavior for the collection end @@ -624,10 +626,19 @@ # special behavior to be applied to each member in the collection end end ``` +## Reusing context objects + +If you create a context object and need to use the same type of object with new role players, you may use the `rebind` method. It will clear any instance_variables from your context object and map the given objects to their names: + +```ruby +context = Employment.new(current_user, the_boss) +context.rebind(employee: another_user, boss: someone_else) # same context, new players +``` + ## Overview in code Here's a view of the possibilities in code. ```ruby @@ -745,9 +756,22 @@ forward_trigger :role_name, :method_name forward_trigger :role_name, :method_name, :alternative_trigger_name_for_method_name forward_triggers :role_name, :list, :of, :methods, :to, :forward forwarding [:list, :of, :methods, :to, :forward] => :role_name end + +# with keyword_initialize (will be changed to initialize) +context = ActiviatingAccount.new(activator: some_object, account: some_account) +# with initialize (this will be moved to initialize_without_keywords) +context = ActiviatingAccount.new(some_object, some_account) +context.triggers # => lists a Set of triggers +# when using protect_triggers +context.triggers # => lists a Set of triggers which may currently be called +context.triggers # => lists a Set of all triggers (the same as if protect_triggers was _not_ used) +context.allow?(:trigger_name) # => returns a boolean if the trigger may be run + +# reuse the context object with new role players +context.rebind(activator: another_object, account: another_account) ``` ## Dependencies The dependencies are minimal. The plan is to keep it that way but allow you to configure things as you need. The [Triad](http://github.com/saturnflyer/triad) project was written specifically to manage the mapping of roles and objects to the modules which contain the behaviors. It is used in Surrounded to keep track of role player, roles, and role constant names but it is not a hard requirement. You may implement your own but presently you'll need to dive into the implementation to fully understand how. Future updates may provide better support and guidance.