README.md in surrounded-0.6.0 vs README.md in surrounded-0.7.0
- old
+ new
@@ -273,10 +273,44 @@
This will allow you to write methods like you normally would. They are aliased internally with a prefix and the method name that you use is rewritten to add and remove the context for the objects in this context. The public API of your class remains the same, but the extra feature of wrapping your method is handled for you.
This works like Ruby's `public`,`protected`, and `private` keywords in that you can send symbols of method names to it. But `trigger` does not alter the parsing of the document like those core keywords do. In other words, you can't merely type `trigger` on one line, and have methods added afterward be treated as trigger methods.
+## Access Control for Triggers
+
+If you decide to build a user interface from the available triggers, you'll find you need to know what triggers are available.
+
+Fortunately, you can make it easy.
+
+By running `protect_triggers` you'll be able to define when triggers may or may not be run. You can still run them, but they'll raise an error. Here's an example.
+
+```ruby
+class MyEnvironment
+ extend Surrounded::Context
+ protect_triggers
+
+ def shove_it
+ employee.quit
+ end
+ trigger :shove_it
+
+ disallow :shove_it do
+ employee.bank_balance < 100
+ end
+end
+```
+
+Then, when the employee role's `bank_balance` is less than `100`, the available triggers won't include `:shove_it`.
+
+You can compare the instance of the context by listing `all_triggers` and `triggers` to see what could be possible and what's currently possible.
+
+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.
+
## 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.
@@ -436,16 +470,25 @@
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
role :activator do # module by default
def some_behavior; end
end
- # role :activator, :module do
+ # role_methods :activator, :module do # alternatively use role_methods if you choose
# def some_behavior; end
# end
#
# role :activator, :wrap do
# def some_behavior; end
@@ -455,20 +498,23 @@
# def some_behavior; end
# end
#
# use your own classes if you don't want SimpleDelegator
# class SomeSpecialRole
- # include Surrounded # you must remember this
+ # include Surrounded # <-- you must remember this in your own classes
# # Surrounded assumes SomeSpecialRole.new(some_special_role)
# def initialize(...);
# # ... your code here
# end
# end
- # works as a trigger (assigning the current context) only if set_methods_as_triggers is set
+ # if you use a regular method and want to use context-specific behavior,
+ # you must handle storing the context yourself:
def regular_method
+ apply_roles # handles the adding of all the roles and behaviors
activator.some_behavior # behavior not available unless you apply roles on initialize
+ remove_roles # handles the removal of all roles and behaviors
end
trigger :some_trigger_method do
activator.some_behavior # behavior always available
end
@@ -478,10 +524,21 @@
end
def regular_non_trigger
activator.some_behavior # behavior always available with the following line
end
- trigger :regular_non_trigger # turns the method into a trigger
+ trigger :regular_non_trigger # turns the method into a trigger
+
+ # create restrictions on what triggers may be used
+ protect_triggers # <-- this is required if you want to protect your triggers this way.
+ disallow :some_trigger_method do
+ # whatever conditional code for the instance of the context
+ end
+
+ # or define your own method without the `disallow` keyword
+ def disallow_some_trigger_method?
+ # whatever conditional code for the instance of the context
+ end
end
```
## Dependencies