README.md in surrounded-0.8.1 vs README.md in surrounded-0.8.2

- old
+ new

@@ -12,11 +12,11 @@ The purpose of this library is to clear away the details of getting things setup and to allow you to make changes to the way you handle roles. There are two main parts to this library. 1. `Surrounded` gives objects an implicit awareness of other objects in their environments. -2. `Surrounded::Context` helps you create objects which encapsulate other objects. These *are* the environments. +2. `Surrounded::Context` helps you create objects which encapsulate other objects **and** their behavior. These *are* the environments. First, take a look at creating contexts. This is where you'll spend most of your time. ## Easily create encapsulated environments for your objects. @@ -305,12 +305,29 @@ Alternatively, if you just want to define your own methods without the DSL using `disallow`, you can just follow the pattern of `disallow_#{method_name}?` when creating your own protection. In fact, that's exactly what happens with the `disallow` keyword. After using it here, we'd have a `disallow_shove_it?` method defined. -If you call the disallowed trigger directly, you'll raise a `Surrounded::Context::AccessError` exception and the code in your trigger will not be run. +If you call the disallowed trigger directly, you'll raise a `MyEnvironment::AccessError` exception and the code in your trigger will not be run. You may rescue from that or you may rescue from `Surrounded::Context::AccessError` although you should prefer to use the error name from your own class. +## Restricting return values + +_Tell, Don't Ask_ style programming can better be enforced by following East-oriented Code principles. This means that the returns values from methods on your objects should not provide information about their internal state. Instead of returning values, you can enforce that triggers return the context object. This forces you to place context responsiblities inside the context and prevents leaking the details and responsiblities outside of the system. + +Here's how you enforce it: + +```ruby +class MyEnvironment + extend Surrounded::Context + east_oriented_triggers +end +``` + +That's it. + +With that change, any trigger you define will execute the block you provide and return `self`, being the instance of the context. + ## Where roles exist By using `Surrounded::Context` you are declaring a relationship between the objects inside playing your defined roles. Because all the behavior is defined internally and only relevant internally, those relationships don't exist outside of the environment. @@ -470,19 +487,13 @@ def initialize(activator, account) # this must be done to handle the mapping of roles to objects # pass an array of arrays with role name symbol and the object for that role map_roles([[:activator, activator],[:account, account]]) end - - # if you want to stick with the `initialize` shortcut you can define these methods - # for special initialization behavior. - def preinitialize - # to happen before any role mapping - end - def postinitialize - # to happen after any role mapping - end + # these also must be done if you create your own initialize method. + # this is a shortcut for using attr_reader and private + private_attr_reader :activator, :account role :activator do # module by default def some_behavior; end end @@ -546,9 +557,13 @@ # Alterantively, you could implement shortcuts individually: def self.some_trigger_method(activator, account) instance = self.new(activator, account) instance.some_trigger_method end + + # Set triggers to always return the context object + # so you can enforce East-oriented style or Tell, Don't Ask + east_oriented_triggers end ``` ## Dependencies