README.md in surrounded-0.1.0 vs README.md in surrounded-0.2.0

- old
+ new

@@ -1,10 +1,11 @@ # Surrounded [![Build Status](https://travis-ci.org/saturnflyer/surrounded.png?branch=master)](https://travis-ci.org/saturnflyer/surrounded) [![Code Climate](https://codeclimate.com/github/saturnflyer/surrounded.png)](https://codeclimate.com/github/saturnflyer/surrounded) [![Coverage Status](https://coveralls.io/repos/saturnflyer/surrounded/badge.png)](https://coveralls.io/r/saturnflyer/surrounded) +[![Gem Version](https://badge.fury.io/rb/surrounded.png)](http://badge.fury.io/rb/surrounded) ## Create encapsulated environments for your objects. Keep the distraction of other features out of your way. Write use cases and focus on just the business logic @@ -43,11 +44,11 @@ extend Surrounded::Context attr_reader :employee, :boss private :employee, :boss def initialize(employee, boss) - @employee = employee.extend(Exmployee) + @employee = employee.extend(Employee) @boss = boss end module Employee # extra behavior here... @@ -105,13 +106,13 @@ ```ruby class MyEnvironment # other stuff from above is still here... def shove_it - Thread.current[:context] = self + employee.store_context(self) employee.quit - Thread.current[:context] = nil + employee.remove_context end module Employee def quit say("I'm sick of this place, #{boss.name}!") @@ -139,11 +140,11 @@ _OK. I think I understand. So I can change business logic just by changing the procedures and the objects. I don't need to adjust arguments for a new requirement. That's kind of cool!_ Damn right. -But you don't want to continually set those `Thread` variables, do you? +But you don't want to continually set those context details, do you? _No. That's annoying._ Yeah. Instead, it would be easier to have this library do the work for us. Here's what you can do: @@ -156,11 +157,11 @@ employee.quit end end ``` -By using this `trigger` keyword, our block is the code we care about, but internally the method is written to set the `Thread` variables. +By using this `trigger` keyword, our block is the code we care about, but internally the method is written to set the `@__surroundings__` collection. _Hmm. I don't like having to do that._ Me either. I'd rather just use `def` but getting automatic code for setting the context is really convenient. It also allows us to store the triggers so that you can, for example, provide details outside of the environment about what triggers exist. @@ -170,24 +171,77 @@ context.triggers #=> [:shove_it] ``` You might find that useful for dynamically defining user interfaces. +## Policies for the application of role methods + +There are 2 approaches to applying new behavior to your objects. + +By default your context will add methods to an object before a trigger is run +and behaviors will be removed after the trigger is run. + +Alternatively you may set the behaviors to be added during the initialize method +of your context. + +Here's how it works: + +```ruby +class ActiviatingAccount + extend Surrounded::Context + + apply_roles_on(:trigger) # this is the default + # apply_roles_on(:initialize) # set this to apply behavior from the start + + setup(:activator, :account) + + module Activator + def some_behavior; end + end + + def non_trigger_method + activator.some_behavior # not available unless you apply roles on initialize + end + + trigger :some_trigger_method do + activator.some_behavior # always available + end +end +``` + +_Why are those options there?_ + +When you initialize a context and apply behavior at the same time, you'll need +to remove that behavior. For example, if you are using Casting AND you apply roles on initialize: + +```ruby +context = ActiviatingAccount.new(current_user, Account.find(123)) +context.do_something +current_user.some_behavior # this method is still available +current_user.uncast # you'll have to manually cleanup +``` + +But if you go with the default and apply behaviors on trigger, your roles will be cleaned up automatically: + +```ruby +context = ActiviatingAccount.new(current_user, Account.find(123)) +context.do_something +current_user.some_behavior # NoMethodError +``` + ## Dependencies The dependencies are minimal. The plan is to keep it that way but allow you to configure things as you need. If you're using [Casting](http://github.com/saturnflyer/casting), for example, Surrounded will attempt to use that before extending an object, but it will still work without it. -## To Do - -Casting provides a way to remove features outside of a block. For now, the code doesn't attempt to `uncast` an object. It will in the future though. - ## Installation Add this line to your application's Gemfile: - gem 'surrounded' +```ruby +gem 'surrounded' +``` And then execute: $ bundle