surrounded 0.7.3 → 0.8.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +1 -1
- data/images/body-bg.png +0 -0
- data/images/highlight-bg.jpg +0 -0
- data/images/hr.png +0 -0
- data/images/octocat-icon.png +0 -0
- data/images/surrounded.png +0 -0
- data/images/tar-gz-icon.png +0 -0
- data/images/zip-icon.png +0 -0
- data/index.html +544 -0
- data/javascripts/main.js +1 -0
- data/javascripts/scale.fix.js +17 -0
- data/lib/surrounded/context.rb +61 -10
- data/lib/surrounded/version.rb +1 -1
- data/lib/surrounded.rb +17 -31
- data/params.json +1 -0
- data/stylesheets/print.css +226 -0
- data/stylesheets/pygment_trac.css +69 -0
- data/stylesheets/styles.css +255 -0
- data/stylesheets/stylesheet.css +371 -0
- data/test/surrounded_test.rb +16 -25
- metadata +30 -15
@@ -0,0 +1,17 @@
|
|
1
|
+
var metas = document.getElementsByTagName('meta');
|
2
|
+
var i;
|
3
|
+
if (navigator.userAgent.match(/iPhone/i)) {
|
4
|
+
for (i=0; i<metas.length; i++) {
|
5
|
+
if (metas[i].name == "viewport") {
|
6
|
+
metas[i].content = "width=device-width, minimum-scale=1.0, maximum-scale=1.0";
|
7
|
+
}
|
8
|
+
}
|
9
|
+
document.addEventListener("gesturestart", gestureStart, false);
|
10
|
+
}
|
11
|
+
function gestureStart() {
|
12
|
+
for (i=0; i<metas.length; i++) {
|
13
|
+
if (metas[i].name == "viewport") {
|
14
|
+
metas[i].content = "width=device-width, minimum-scale=0.25, maximum-scale=1.6";
|
15
|
+
}
|
16
|
+
}
|
17
|
+
}
|
data/lib/surrounded/context.rb
CHANGED
@@ -5,16 +5,24 @@ require 'surrounded/shortcuts'
|
|
5
5
|
|
6
6
|
# Some features are only available in versions of Ruby
|
7
7
|
# where this method is true
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
8
|
+
unless defined?(module_method_rebinding?)
|
9
|
+
def module_method_rebinding?
|
10
|
+
return @__module_method_rebinding__ if defined?(@__module_method_rebinding__)
|
11
|
+
sample_method = Enumerable.instance_method(:to_a)
|
12
|
+
@__module_method_rebinding__ = begin
|
13
|
+
!!sample_method.bind(Object.new)
|
14
|
+
rescue TypeError
|
15
|
+
false
|
16
|
+
end
|
15
17
|
end
|
16
18
|
end
|
17
19
|
|
20
|
+
# Extend your classes with Surrounded::Context to handle their
|
21
|
+
# initialization and application of behaviors to the role players
|
22
|
+
# passed into the constructor.
|
23
|
+
#
|
24
|
+
# The purpose of this module is to help you create context objects
|
25
|
+
# which encapsulate the interaction and behavior of objects inside.
|
18
26
|
module Surrounded
|
19
27
|
module Context
|
20
28
|
def self.extended(base)
|
@@ -32,12 +40,16 @@ module Surrounded
|
|
32
40
|
instance
|
33
41
|
end
|
34
42
|
|
43
|
+
# Provides a Set of all available trigger methods where
|
44
|
+
# behaviors will be applied to the roles before execution
|
45
|
+
# and removed afterward.
|
35
46
|
def triggers
|
36
47
|
@triggers.dup
|
37
48
|
end
|
38
49
|
|
39
50
|
private
|
40
51
|
|
52
|
+
# Set the default type of implementation for role methods for all contexts.
|
41
53
|
def self.default_role_type
|
42
54
|
@default_role_type ||= :module
|
43
55
|
end
|
@@ -47,7 +59,11 @@ module Surrounded
|
|
47
59
|
end
|
48
60
|
|
49
61
|
# Additional Features
|
62
|
+
|
63
|
+
# Provide the ability to create access control methods for your triggers.
|
50
64
|
def protect_triggers; self.extend(::Surrounded::AccessControl); end
|
65
|
+
|
66
|
+
# Automatically create class methods for each trigger method.
|
51
67
|
def shortcut_triggers; self.extend(::Surrounded::Shortcuts); end
|
52
68
|
|
53
69
|
def private_const_set(name, const)
|
@@ -60,10 +76,12 @@ module Surrounded
|
|
60
76
|
@default_role_type ||= Surrounded::Context.default_role_type
|
61
77
|
end
|
62
78
|
|
79
|
+
# Set the default type of implementation for role method for an individual context.
|
63
80
|
def default_role_type=(type)
|
64
81
|
@default_role_type = type
|
65
82
|
end
|
66
83
|
|
84
|
+
# Create a named behavior for a role using the standard library SimpleDelegator.
|
67
85
|
def wrap(name, &block)
|
68
86
|
require 'delegate'
|
69
87
|
wrapper_name = name.to_s.gsub(/(?:^|_)([a-z])/){ $1.upcase }
|
@@ -73,6 +91,7 @@ module Surrounded
|
|
73
91
|
alias_method :wrapper, :wrap
|
74
92
|
|
75
93
|
if module_method_rebinding?
|
94
|
+
# Create an object which will bind methods to the role player
|
76
95
|
def interface(name, &block)
|
77
96
|
class_basename = name.to_s.gsub(/(?:^|_)([a-z])/){ $1.upcase }
|
78
97
|
interface_name = class_basename + 'Interface'
|
@@ -80,12 +99,14 @@ module Surrounded
|
|
80
99
|
behavior = private_const_set(interface_name, Module.new(&block))
|
81
100
|
|
82
101
|
require 'surrounded/context/negotiator'
|
102
|
+
undef_method(name)
|
83
103
|
define_method(name) do
|
84
104
|
instance_variable_set("@#{name}", Negotiator.new(role_map.assigned_player(name), behavior))
|
85
105
|
end
|
86
106
|
end
|
87
107
|
end
|
88
108
|
|
109
|
+
# Define behaviors for your role players
|
89
110
|
def role(name, type=nil, &block)
|
90
111
|
role_type = type || default_role_type
|
91
112
|
if role_type == :module
|
@@ -108,6 +129,8 @@ module Surrounded
|
|
108
129
|
@__apply_role_policy ||= :trigger
|
109
130
|
end
|
110
131
|
|
132
|
+
# Shorthand for creating an instance level initialize method which
|
133
|
+
# handles the mapping of the given arguments to their named role.
|
111
134
|
def initialize(*setup_args)
|
112
135
|
private_attr_reader(*setup_args)
|
113
136
|
|
@@ -127,6 +150,22 @@ module Surrounded
|
|
127
150
|
private(*method_names)
|
128
151
|
end
|
129
152
|
|
153
|
+
# Creates a context instance method which will apply behaviors to role players
|
154
|
+
# before execution and remove the behaviors after execution.
|
155
|
+
#
|
156
|
+
# Alternatively you may define your own methods then declare them as triggers
|
157
|
+
# afterward.
|
158
|
+
#
|
159
|
+
# Example:
|
160
|
+
# trigger :some_event do
|
161
|
+
# # code here
|
162
|
+
# end
|
163
|
+
#
|
164
|
+
# def some_event
|
165
|
+
# # code here
|
166
|
+
# end
|
167
|
+
# trigger :some_event
|
168
|
+
#
|
130
169
|
def trigger(*names, &block)
|
131
170
|
if block.nil?
|
132
171
|
names.each do |name|
|
@@ -180,12 +219,20 @@ module Surrounded
|
|
180
219
|
end
|
181
220
|
|
182
221
|
module InstanceMethods
|
222
|
+
# Check whether a given name is a role inside the context.
|
223
|
+
# The provided block is used to evaluate whether or not the caller
|
224
|
+
# is allowed to inquire about the roles.
|
183
225
|
def role?(name, &block)
|
184
226
|
return false unless role_map.role?(name)
|
185
|
-
accessor = eval('self'
|
227
|
+
accessor = block.binding.eval('self')
|
186
228
|
role_map.role_player?(accessor) && role_map.assigned_player(name)
|
187
229
|
end
|
188
230
|
|
231
|
+
# Check if a given object is a role player in the context.
|
232
|
+
def role_player?(obj)
|
233
|
+
role_map.role_player?(obj)
|
234
|
+
end
|
235
|
+
|
189
236
|
def triggers
|
190
237
|
self.class.triggers
|
191
238
|
end
|
@@ -224,7 +271,7 @@ module Surrounded
|
|
224
271
|
|
225
272
|
role_player = applicator.call(object, behavior)
|
226
273
|
map_role(role, role_module_basename(behavior), role_player) if behavior
|
227
|
-
role_player.store_context
|
274
|
+
role_player.send(:store_context, self){}
|
228
275
|
role_player
|
229
276
|
end
|
230
277
|
|
@@ -247,7 +294,7 @@ module Surrounded
|
|
247
294
|
remover_name = (module_removal_methods + unwrap_methods).find{|meth| object.respond_to?(meth) }
|
248
295
|
return object if !remover_name
|
249
296
|
|
250
|
-
object.remove_context
|
297
|
+
object.send(:remove_context) do; end
|
251
298
|
role_player = object.method(remover_name).call
|
252
299
|
|
253
300
|
map_role(role, role_module_basename(behavior), role_player) if behavior
|
@@ -271,18 +318,22 @@ module Surrounded
|
|
271
318
|
end
|
272
319
|
end
|
273
320
|
|
321
|
+
# List of possible methods to use to add behavior to an object from a module.
|
274
322
|
def module_extension_methods
|
275
323
|
[:cast_as, :extend]
|
276
324
|
end
|
277
325
|
|
326
|
+
# List of possible methods to use to add behavior to an object from a wrapper.
|
278
327
|
def wrap_methods
|
279
328
|
[:new]
|
280
329
|
end
|
281
330
|
|
331
|
+
# List of possible methods to use to remove behavior from an object with a module.
|
282
332
|
def module_removal_methods
|
283
333
|
[:uncast]
|
284
334
|
end
|
285
335
|
|
336
|
+
# List of possible methods to use to remove behavior from an object with a wrapper.
|
286
337
|
def unwrap_methods
|
287
338
|
[:__getobj__]
|
288
339
|
end
|
data/lib/surrounded/version.rb
CHANGED
data/lib/surrounded.rb
CHANGED
@@ -1,46 +1,32 @@
|
|
1
1
|
require "surrounded/version"
|
2
2
|
require "surrounded/context"
|
3
3
|
|
4
|
+
# This module should be added to objects which will enter
|
5
|
+
# into context objects.
|
6
|
+
#
|
7
|
+
# Its main purpose is to keep a reference to the context
|
8
|
+
# and to implement method_missing to handle the relationship
|
9
|
+
# to other objects in the context.
|
4
10
|
module Surrounded
|
5
|
-
def self.included(klass)
|
6
|
-
klass.class_eval {
|
7
|
-
extend Surrounded::Contextual
|
8
|
-
}
|
9
|
-
unless klass.is_a?(Class)
|
10
|
-
def klass.extended(object)
|
11
|
-
Surrounded.create_surroundings(object)
|
12
|
-
end
|
13
|
-
end
|
14
|
-
end
|
15
11
|
|
16
|
-
|
17
|
-
Surrounded.create_surroundings(object)
|
18
|
-
end
|
12
|
+
private
|
19
13
|
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
instance
|
14
|
+
def store_context(ctxt, &block)
|
15
|
+
accessor = block.binding.eval('self')
|
16
|
+
if accessor.role_player?(self)
|
17
|
+
surroundings.unshift(ctxt)
|
25
18
|
end
|
26
19
|
end
|
27
20
|
|
28
|
-
def
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
surroundings.shift
|
34
|
-
end
|
35
|
-
|
36
|
-
private
|
37
|
-
|
38
|
-
def self.create_surroundings(obj)
|
39
|
-
obj.instance_variable_set(:@__surroundings__, [])
|
21
|
+
def remove_context(&block)
|
22
|
+
accessor = block.binding.eval('self')
|
23
|
+
if accessor.role_player?(self)
|
24
|
+
surroundings.shift
|
25
|
+
end
|
40
26
|
end
|
41
27
|
|
42
28
|
def surroundings
|
43
|
-
@__surroundings__
|
29
|
+
@__surroundings__ ||= []
|
44
30
|
end
|
45
31
|
|
46
32
|
def context
|
data/params.json
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
{"name":"Surrounded","tagline":"Gives an object implicit access to other objects in it's environment.","body":"# ![Surrounded](http://saturnflyer.github.io/surrounded/images/surrounded.png \"Surrounded\")\r\n## Bring your own complexity\r\n\r\n[![Build Status](https://travis-ci.org/saturnflyer/surrounded.png?branch=master)](https://travis-ci.org/saturnflyer/surrounded)\r\n[![Code Climate](https://codeclimate.com/github/saturnflyer/surrounded.png)](https://codeclimate.com/github/saturnflyer/surrounded)\r\n[![Coverage Status](https://coveralls.io/repos/saturnflyer/surrounded/badge.png)](https://coveralls.io/r/saturnflyer/surrounded)\r\n[![Gem Version](https://badge.fury.io/rb/surrounded.png)](http://badge.fury.io/rb/surrounded)\r\n\r\n# Surrounded aims to make things simple and get out of your way.\r\n\r\nMost of what you care about is defining the behavior of objects. How they interact is important.\r\nThe 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.\r\n\r\nThere are two main parts to this library. \r\n\r\n1. `Surrounded` gives objects an implicit awareness of other objects in their environments.\r\n2. `Surrounded::Context` helps you create objects which encapsulate other objects. These *are* the environments.\r\n\r\nFirst, take a look at creating contexts. This is where you'll spend most of your time.\r\n\r\n## Easily create encapsulated environments for your objects.\r\n\r\nTypical initialization of an environment, or a Context in DCI, has a lot of code. For example:\r\n\r\n```ruby\r\nclass MyEnvironment\r\n\r\n attr_reader :employee, :boss\r\n private :employee, :boss\r\n def initialize(employee, boss)\r\n @employee = employee.extend(Employee)\r\n @boss = boss\r\n end\r\n\r\n module Employee\r\n # extra behavior here...\r\n end\r\nend\r\n```\r\n\r\nThis code allows the MyEnvironment class to create instances where it will have an `employee` and a `boss` role internally. These are set to `attr_reader`s and are made private.\r\n\r\nThe `employee` is extended with behaviors defined in the `Employee` module, and in this case there's no extra stuff for the `boss` so it doesn't get extended with anything.\r\n\r\nMost of the time you'll follow a pattern like this. Some objects will get extra behavior and some won't. The modules that you use to provide the behavior will match the names you use for the roles to which you assign objects.\r\n\r\nBy adding `Surrounded::Context` you can shortcut all this work.\r\n\r\n```ruby\r\nclass MyEnvironment\r\n extend Surrounded::Context\r\n \r\n initialize(:employee, :boss)\r\n\r\n module Employee\r\n # extra behavior here...\r\n end\r\nend\r\n```\r\n\r\nSurrounded gives you an `initialize` class method which does all the setup work for you.\r\n\r\n## Managing Roles\r\n\r\n_I don't want to use modules. Can't I use something like SimpleDelegator?_\r\n\r\nWell, it just so happens that you can. This code will work just fine:\r\n\r\n```ruby\r\nclass MyEnvironment\r\n extend Surrounded::Context\r\n \r\n initialize(:employee, :boss)\r\n\r\n class Employee < SimpleDelegator\r\n # extra behavior here...\r\n end\r\nend\r\n```\r\n\r\nInstead of extending the `employee` object, Surrounded will run `Employee.new(employee)` to create the wrapper for you. You'll need to include the `Surrounded` module in your wrapper, but we'll get to that.\r\n\r\nBut the syntax can be even simpler than that if you want.\r\n\r\n```ruby\r\nclass MyEnvironment\r\n extend Surrounded::Context\r\n \r\n initialize(:employee, :boss)\r\n\r\n role :employee do\r\n # extra behavior here...\r\n end\r\nend\r\n```\r\n\r\nBy default, this code will create a module for you named `Employee`. If you want to use a wrapper, you can do this:\r\n\r\n```ruby\r\nclass MyEnvironment\r\n extend Surrounded::Context\r\n \r\n initialize(:employee, :boss)\r\n\r\n wrap :employee do\r\n # extra behavior here...\r\n end\r\nend\r\n```\r\n\r\nBut if you're making changes and you decide to move from a module to a wrapper or from a wrapper to a module, you'll need to change that method call. Instead, you could just tell it which type of role to use:\r\n\r\n```ruby\r\nclass MyEnvironment\r\n extend Surrounded::Context\r\n \r\n initialize(:employee, :boss)\r\n\r\n role :employee, :wrapper do\r\n # extra behavior here...\r\n end\r\nend\r\n```\r\n\r\nThe default available types are `:module`, `:wrap` or `:wrapper`, and `:interface`. We'll get to `interface` below. The `:wrap` and `:wrapper` types are the same and they'll both create classes which inherit from SimpleDelegator _and_ include Surrounded for you.\r\n\r\nThese are minor little changes which highlight how simple it is to use Surrounded.\r\n\r\n_Well... I want to use [Casting](https://github.com/saturnflyer/casting) so I get the benefit of modules without extending objects. Can I do that?_\r\n\r\nYup. The ability to use Casting is built-in. If the objects you provide to your context respond to `cast_as` then Surrounded will use that.\r\n\r\n_Ok. So is that it?_\r\n\r\nThere's a lot more. Let's look at the individual objects and what they need for this to be valuable...\r\n\r\n## Objects' access to their environments\r\n\r\nAdd `Surrounded` to your objects to give them awareness of other objects.\r\n\r\n```ruby\r\nclass User\r\n include Surrounded\r\nend\r\n```\r\n\r\nNow the `User` instances will be able to implicitly access objects in their environment.\r\n\r\nVia `method_missing` those `User` instances can access a `context` object it stores in an internal collection. \r\n\r\nInside of the `MyEnvironment` context we saw above, the `employee` and `boss` objects are instances of `User` for this example.\r\n\r\nBecause the `User` class includes `Surrounded`, the instances of that class will be able to access other objects in the same context implicitly.\r\n\r\nLet's make our context look like this:\r\n\r\n```ruby\r\nclass MyEnvironment\r\n # other stuff from above is still here...\r\n\r\n def shove_it\r\n employee.quit\r\n end\r\n\r\n role :employee do\r\n def quit\r\n say(\"I'm sick of this place, #{boss.name}!\")\r\n stomp\r\n throw_papers\r\n say(\"I quit!\")\r\n end\r\n end\r\nend\r\n```\r\n\r\nWhat's happening in there is that when the `shove_it` method is called on the instance of `MyEnvironment`, the `employee` has the ability to refer to `boss` because it is in the same context, e.g. the same environment.\r\n\r\nThe behavior defined in the `Employee` module assumes that it may access other objects in it's local environment. The `boss` object, for example, is never explicitly passed in as an argument.\r\n\r\nWhat `Surrounded` does for us is to make the relationship between objects and gives them the ability to access each other. Adding new or different roles to the context now only requires that we add them to the context and nothing else. No explicit references must be passed to each individual method. The objects are aware of the other objects around them and can refer to them by their role name.\r\n\r\nI didn't mention how the context is set, however.\r\n\r\n## Tying objects together\r\n\r\nYour context will have methods of it's own which will trigger actions on the objects inside, but we need those trigger methods to set the accessible context for each of the contained objects.\r\n\r\nHere's an example of what we want:\r\n\r\n```ruby\r\nclass MyEnvironment\r\n # other stuff from above is still here...\r\n\r\n def shove_it\r\n employee.store_context(self)\r\n employee.quit\r\n employee.remove_context\r\n end\r\n\r\n role :employee do\r\n def quit\r\n say(\"I'm sick of this place, #{boss.name}!\")\r\n stomp\r\n throw_papers\r\n say(\"I quit!\")\r\n end\r\n end\r\nend\r\n```\r\n\r\nNow that the `employee` has a reference to the context, it won't blow up when it hits `boss` inside that `quit` method.\r\n\r\nWe saw how we were able to clear up a lot of that repetitive work with the `initialize` method, so this is how we do it here:\r\n\r\n```ruby\r\nclass MyEnvironment\r\n # other stuff from above is still here...\r\n\r\n trigger :shove_it do\r\n employee.quit\r\n end\r\n\r\n role :employee do\r\n def quit\r\n say(\"I'm sick of this place, #{boss.name}!\")\r\n stomp\r\n throw_papers\r\n say(\"I quit!\")\r\n end\r\n end\r\nend\r\n```\r\n\r\nBy using this `trigger` keyword, our block is the code we care about, but internally the method is created to first set all the objects' current contexts.\r\n\r\nThe context will also store the triggers so that you can, for example, provide details outside of the environment about what triggers exist.\r\n\r\n```ruby\r\ncontext = MyEnvironment.new(current_user, the_boss)\r\ncontext.triggers #=> [:shove_it]\r\n```\r\n\r\nYou might find that useful for dynamically defining user interfaces.\r\n\r\nSometimes I'd rather not use this DSL, however. I want to just write regular methods. \r\n\r\nWe can do that too. You'll need to opt in to this by specifying `set_methods_as_triggers` for the context class.\r\n\r\n```ruby\r\nclass MyEnvironment\r\n # other stuff from above is still here...\r\n \r\n set_methods_as_triggers\r\n\r\n def shove_it\r\n employee.quit\r\n end\r\n\r\n role :employee do\r\n def quit\r\n say(\"I'm sick of this place, #{boss.name}!\")\r\n stomp\r\n throw_papers\r\n say(\"I quit!\")\r\n end\r\n end\r\nend\r\n```\r\n\r\nThis 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.\r\n\r\nThis will treat all instance methods defined on your context the same way, so be aware of that.\r\n\r\n## Where roles exist\r\n\r\nBy using `Surrounded::Context` you are declaring a relationship between the objects inside playing your defined roles.\r\n\r\nBecause all the behavior is defined internally and only relevant internally, those relationships don't exist outside of the environment.\r\n\r\nSurrounded makes all of your role modules and classes private constants. It's not a good idea to try to reuse behavior defined for one context in another area.\r\n\r\n## The role DSL\r\n\r\nUsing the `role` method to define modules and classes takes care of the setup for you. This way you can swap between implementations:\r\n\r\n```ruby\r\n\r\n # this uses modules\r\n role :source do\r\n def transfer\r\n self.balance -= amount\r\n destination.balance += amount\r\n self\r\n end\r\n end\r\n\r\n # this uses SimpleDelegator and Surrounded\r\n role :source, :wrap do\r\n def transfer\r\n self.balance -= amount\r\n destination.balance += amount\r\n __getobj__\r\n end\r\n end\r\n\r\n # this uses a special interface object which pulls\r\n # methods from a module and applies them to your object.\r\n role :source, :interface do\r\n def transfer\r\n self.balance -= amount\r\n destination.balance += amount\r\n self\r\n end\r\n end\r\n```\r\n\r\nThe `:interface` option is a special object which has all of its methods removed (excepting `__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.\r\n\r\nNotice 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__`.\r\n\r\nIf you'd like to choose one and use it all the time, you can set the default:\r\n\r\n```ruby\r\nclass MoneyTransfer\r\n extend Surrounded::Context\r\n\r\n self.default_role_type = :interface # also :wrap, :wrapper, or :module\r\n\r\n role :source do\r\n def transfer\r\n self.balance -= amount\r\n destination.balance += amount\r\n self\r\n end\r\n end\r\nend\r\n```\r\n\r\nOr, if you like, you can choose the default for your entire project:\r\n\r\n```ruby\r\nSurrounded::Context.default_role_type = :interface\r\n\r\nclass MoneyTransfer\r\n extend Surrounded::Context\r\n\r\n role :source do\r\n def transfer\r\n self.balance -= amount\r\n destination.balance += amount\r\n self\r\n end\r\n end\r\nend\r\n```\r\n\r\n## Policies for the application of role methods\r\n\r\nThere are 2 approaches to applying new behavior to your objects.\r\n\r\nBy default your context will add methods to an object before a trigger is run\r\nand behaviors will be removed after the trigger is run.\r\n\r\nAlternatively you may set the behaviors to be added during the initialize method\r\nof your context.\r\n\r\nHere's how it works:\r\n\r\n```ruby\r\nclass ActiviatingAccount\r\n extend Surrounded::Context\r\n\r\n apply_roles_on(:trigger) # this is the default\r\n # apply_roles_on(:initialize) # set this to apply behavior from the start\r\n\r\n initialize(:activator, :account)\r\n\r\n role :activator do\r\n def some_behavior; end\r\n end\r\n\r\n def non_trigger_method\r\n activator.some_behavior # not available unless you apply roles on initialize\r\n end\r\n\r\n trigger :some_trigger_method do\r\n activator.some_behavior # always available\r\n end\r\nend\r\n```\r\n\r\n_Why are those options there?_\r\n\r\nWhen you initialize a context and apply behavior at the same time, you'll need\r\nto remove that behavior. For example, if you are using Casting AND you apply roles on initialize:\r\n\r\n```ruby\r\ncontext = ActiviatingAccount.new(current_user, Account.find(123))\r\ncontext.do_something\r\ncurrent_user.some_behavior # this method is still available\r\ncurrent_user.uncast # you'll have to manually cleanup\r\n```\r\n\r\nBut if you go with the default and apply behaviors on trigger, your roles will be cleaned up automatically:\r\n\r\n```ruby\r\ncontext = ActiviatingAccount.new(current_user, Account.find(123))\r\ncontext.do_something\r\ncurrent_user.some_behavior # NoMethodError\r\n```\r\n\r\n## Overview in code\r\n\r\nHere's a view of the possibilities in code.\r\n\r\n```ruby\r\n# set default role type for *all* contexts in your program\r\nSurrounded::Context.default_role_type = :module # also :wrap, :wrapper, or :interface\r\n\r\nclass ActiviatingAccount\r\n extend Surrounded::Context\r\n\r\n apply_roles_on(:trigger) # this is the default\r\n # apply_roles_on(:initialize) # set this to apply behavior from the start\r\n \r\n set_methods_as_triggers # allows you to skip the 'trigger' dsl\r\n \r\n # set the default role type only for this class\r\n self.default_role_type = :module # also :wrap, :wrapper, or :interface\r\n\r\n initialize(:activator, :account)\r\n\r\n role :activator do # module by default\r\n def some_behavior; end\r\n end\r\n\r\n # role :activator, :module do\r\n # def some_behavior; end\r\n # end\r\n #\r\n # role :activator, :wrap do\r\n # def some_behavior; end\r\n # end\r\n #\r\n # role :activator, :interface do\r\n # def some_behavior; end\r\n # end\r\n #\r\n # use your own classes if you don't want SimpleDelegator\r\n # class SomeSpecialRole\r\n # include Surrounded # you must remember this\r\n # # Surrounded assumes SomeSpecialRole.new(some_special_role)\r\n # def initialize(...);\r\n # # ... your code here\r\n # end\r\n # end\r\n\r\n # works as a trigger (assigning the current context) only if set_methods_as_triggers is set\r\n def regular_method\r\n activator.some_behavior # behavior not available unless you apply roles on initialize\r\n end\r\n\r\n trigger :some_trigger_method do\r\n activator.some_behavior # behavior always available\r\n end\r\nend\r\n```\r\n\r\n## Dependencies\r\n\r\nThe 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.\r\n\r\nIf 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.\r\n\r\n## Installation\r\n\r\nAdd this line to your application's Gemfile:\r\n\r\n```ruby\r\ngem 'surrounded'\r\n```\r\n\r\nAnd then execute:\r\n\r\n $ bundle\r\n\r\nOr install it yourself as:\r\n\r\n $ gem install surrounded\r\n \r\n## Installation for Rails\r\n\r\nSee [surrounded-rails](https://github.com/saturnflyer/surrounded-rails)\r\n\r\n## Contributing\r\n\r\n1. Fork it\r\n2. Create your feature branch (`git checkout -b my-new-feature`)\r\n3. Commit your changes (`git commit -am 'Add some feature'`)\r\n4. Push to the branch (`git push origin my-new-feature`)\r\n5. Create new Pull Request\r\n","google":"","note":"Don't delete this file! It's used internally to help with page regeneration."}
|
@@ -0,0 +1,226 @@
|
|
1
|
+
html, body, div, span, applet, object, iframe,
|
2
|
+
h1, h2, h3, h4, h5, h6, p, blockquote, pre,
|
3
|
+
a, abbr, acronym, address, big, cite, code,
|
4
|
+
del, dfn, em, img, ins, kbd, q, s, samp,
|
5
|
+
small, strike, strong, sub, sup, tt, var,
|
6
|
+
b, u, i, center,
|
7
|
+
dl, dt, dd, ol, ul, li,
|
8
|
+
fieldset, form, label, legend,
|
9
|
+
table, caption, tbody, tfoot, thead, tr, th, td,
|
10
|
+
article, aside, canvas, details, embed,
|
11
|
+
figure, figcaption, footer, header, hgroup,
|
12
|
+
menu, nav, output, ruby, section, summary,
|
13
|
+
time, mark, audio, video {
|
14
|
+
margin: 0;
|
15
|
+
padding: 0;
|
16
|
+
border: 0;
|
17
|
+
font-size: 100%;
|
18
|
+
font: inherit;
|
19
|
+
vertical-align: baseline;
|
20
|
+
}
|
21
|
+
/* HTML5 display-role reset for older browsers */
|
22
|
+
article, aside, details, figcaption, figure,
|
23
|
+
footer, header, hgroup, menu, nav, section {
|
24
|
+
display: block;
|
25
|
+
}
|
26
|
+
body {
|
27
|
+
line-height: 1;
|
28
|
+
}
|
29
|
+
ol, ul {
|
30
|
+
list-style: none;
|
31
|
+
}
|
32
|
+
blockquote, q {
|
33
|
+
quotes: none;
|
34
|
+
}
|
35
|
+
blockquote:before, blockquote:after,
|
36
|
+
q:before, q:after {
|
37
|
+
content: '';
|
38
|
+
content: none;
|
39
|
+
}
|
40
|
+
table {
|
41
|
+
border-collapse: collapse;
|
42
|
+
border-spacing: 0;
|
43
|
+
}
|
44
|
+
body {
|
45
|
+
font-size: 13px;
|
46
|
+
line-height: 1.5;
|
47
|
+
font-family: 'Helvetica Neue', Helvetica, Arial, serif;
|
48
|
+
color: #000;
|
49
|
+
}
|
50
|
+
|
51
|
+
a {
|
52
|
+
color: #d5000d;
|
53
|
+
font-weight: bold;
|
54
|
+
}
|
55
|
+
|
56
|
+
header {
|
57
|
+
padding-top: 35px;
|
58
|
+
padding-bottom: 10px;
|
59
|
+
}
|
60
|
+
|
61
|
+
header h1 {
|
62
|
+
font-weight: bold;
|
63
|
+
letter-spacing: -1px;
|
64
|
+
font-size: 48px;
|
65
|
+
color: #303030;
|
66
|
+
line-height: 1.2;
|
67
|
+
}
|
68
|
+
|
69
|
+
header h2 {
|
70
|
+
letter-spacing: -1px;
|
71
|
+
font-size: 24px;
|
72
|
+
color: #aaa;
|
73
|
+
font-weight: normal;
|
74
|
+
line-height: 1.3;
|
75
|
+
}
|
76
|
+
#downloads {
|
77
|
+
display: none;
|
78
|
+
}
|
79
|
+
#main_content {
|
80
|
+
padding-top: 20px;
|
81
|
+
}
|
82
|
+
|
83
|
+
code, pre {
|
84
|
+
font-family: Monaco, "Bitstream Vera Sans Mono", "Lucida Console", Terminal;
|
85
|
+
color: #222;
|
86
|
+
margin-bottom: 30px;
|
87
|
+
font-size: 12px;
|
88
|
+
}
|
89
|
+
|
90
|
+
code {
|
91
|
+
padding: 0 3px;
|
92
|
+
}
|
93
|
+
|
94
|
+
pre {
|
95
|
+
border: solid 1px #ddd;
|
96
|
+
padding: 20px;
|
97
|
+
overflow: auto;
|
98
|
+
}
|
99
|
+
pre code {
|
100
|
+
padding: 0;
|
101
|
+
}
|
102
|
+
|
103
|
+
ul, ol, dl {
|
104
|
+
margin-bottom: 20px;
|
105
|
+
}
|
106
|
+
|
107
|
+
|
108
|
+
/* COMMON STYLES */
|
109
|
+
|
110
|
+
table {
|
111
|
+
width: 100%;
|
112
|
+
border: 1px solid #ebebeb;
|
113
|
+
}
|
114
|
+
|
115
|
+
th {
|
116
|
+
font-weight: 500;
|
117
|
+
}
|
118
|
+
|
119
|
+
td {
|
120
|
+
border: 1px solid #ebebeb;
|
121
|
+
text-align: center;
|
122
|
+
font-weight: 300;
|
123
|
+
}
|
124
|
+
|
125
|
+
form {
|
126
|
+
background: #f2f2f2;
|
127
|
+
padding: 20px;
|
128
|
+
|
129
|
+
}
|
130
|
+
|
131
|
+
|
132
|
+
/* GENERAL ELEMENT TYPE STYLES */
|
133
|
+
|
134
|
+
h1 {
|
135
|
+
font-size: 2.8em;
|
136
|
+
}
|
137
|
+
|
138
|
+
h2 {
|
139
|
+
font-size: 22px;
|
140
|
+
font-weight: bold;
|
141
|
+
color: #303030;
|
142
|
+
margin-bottom: 8px;
|
143
|
+
}
|
144
|
+
|
145
|
+
h3 {
|
146
|
+
color: #d5000d;
|
147
|
+
font-size: 18px;
|
148
|
+
font-weight: bold;
|
149
|
+
margin-bottom: 8px;
|
150
|
+
}
|
151
|
+
|
152
|
+
h4 {
|
153
|
+
font-size: 16px;
|
154
|
+
color: #303030;
|
155
|
+
font-weight: bold;
|
156
|
+
}
|
157
|
+
|
158
|
+
h5 {
|
159
|
+
font-size: 1em;
|
160
|
+
color: #303030;
|
161
|
+
}
|
162
|
+
|
163
|
+
h6 {
|
164
|
+
font-size: .8em;
|
165
|
+
color: #303030;
|
166
|
+
}
|
167
|
+
|
168
|
+
p {
|
169
|
+
font-weight: 300;
|
170
|
+
margin-bottom: 20px;
|
171
|
+
}
|
172
|
+
|
173
|
+
a {
|
174
|
+
text-decoration: none;
|
175
|
+
}
|
176
|
+
|
177
|
+
p a {
|
178
|
+
font-weight: 400;
|
179
|
+
}
|
180
|
+
|
181
|
+
blockquote {
|
182
|
+
font-size: 1.6em;
|
183
|
+
border-left: 10px solid #e9e9e9;
|
184
|
+
margin-bottom: 20px;
|
185
|
+
padding: 0 0 0 30px;
|
186
|
+
}
|
187
|
+
|
188
|
+
ul li {
|
189
|
+
list-style: disc inside;
|
190
|
+
padding-left: 20px;
|
191
|
+
}
|
192
|
+
|
193
|
+
ol li {
|
194
|
+
list-style: decimal inside;
|
195
|
+
padding-left: 3px;
|
196
|
+
}
|
197
|
+
|
198
|
+
dl dd {
|
199
|
+
font-style: italic;
|
200
|
+
font-weight: 100;
|
201
|
+
}
|
202
|
+
|
203
|
+
footer {
|
204
|
+
margin-top: 40px;
|
205
|
+
padding-top: 20px;
|
206
|
+
padding-bottom: 30px;
|
207
|
+
font-size: 13px;
|
208
|
+
color: #aaa;
|
209
|
+
}
|
210
|
+
|
211
|
+
footer a {
|
212
|
+
color: #666;
|
213
|
+
}
|
214
|
+
|
215
|
+
/* MISC */
|
216
|
+
.clearfix:after {
|
217
|
+
clear: both;
|
218
|
+
content: '.';
|
219
|
+
display: block;
|
220
|
+
visibility: hidden;
|
221
|
+
height: 0;
|
222
|
+
}
|
223
|
+
|
224
|
+
.clearfix {display: inline-block;}
|
225
|
+
* html .clearfix {height: 1%;}
|
226
|
+
.clearfix {display: block;}
|
@@ -0,0 +1,69 @@
|
|
1
|
+
.highlight { background: #ffffff; }
|
2
|
+
.highlight .c { color: #999988; font-style: italic } /* Comment */
|
3
|
+
.highlight .err { color: #a61717; background-color: #e3d2d2 } /* Error */
|
4
|
+
.highlight .k { font-weight: bold } /* Keyword */
|
5
|
+
.highlight .o { font-weight: bold } /* Operator */
|
6
|
+
.highlight .cm { color: #999988; font-style: italic } /* Comment.Multiline */
|
7
|
+
.highlight .cp { color: #999999; font-weight: bold } /* Comment.Preproc */
|
8
|
+
.highlight .c1 { color: #999988; font-style: italic } /* Comment.Single */
|
9
|
+
.highlight .cs { color: #999999; font-weight: bold; font-style: italic } /* Comment.Special */
|
10
|
+
.highlight .gd { color: #000000; background-color: #ffdddd } /* Generic.Deleted */
|
11
|
+
.highlight .gd .x { color: #000000; background-color: #ffaaaa } /* Generic.Deleted.Specific */
|
12
|
+
.highlight .ge { font-style: italic } /* Generic.Emph */
|
13
|
+
.highlight .gr { color: #aa0000 } /* Generic.Error */
|
14
|
+
.highlight .gh { color: #999999 } /* Generic.Heading */
|
15
|
+
.highlight .gi { color: #000000; background-color: #ddffdd } /* Generic.Inserted */
|
16
|
+
.highlight .gi .x { color: #000000; background-color: #aaffaa } /* Generic.Inserted.Specific */
|
17
|
+
.highlight .go { color: #888888 } /* Generic.Output */
|
18
|
+
.highlight .gp { color: #555555 } /* Generic.Prompt */
|
19
|
+
.highlight .gs { font-weight: bold } /* Generic.Strong */
|
20
|
+
.highlight .gu { color: #800080; font-weight: bold; } /* Generic.Subheading */
|
21
|
+
.highlight .gt { color: #aa0000 } /* Generic.Traceback */
|
22
|
+
.highlight .kc { font-weight: bold } /* Keyword.Constant */
|
23
|
+
.highlight .kd { font-weight: bold } /* Keyword.Declaration */
|
24
|
+
.highlight .kn { font-weight: bold } /* Keyword.Namespace */
|
25
|
+
.highlight .kp { font-weight: bold } /* Keyword.Pseudo */
|
26
|
+
.highlight .kr { font-weight: bold } /* Keyword.Reserved */
|
27
|
+
.highlight .kt { color: #445588; font-weight: bold } /* Keyword.Type */
|
28
|
+
.highlight .m { color: #009999 } /* Literal.Number */
|
29
|
+
.highlight .s { color: #d14 } /* Literal.String */
|
30
|
+
.highlight .na { color: #008080 } /* Name.Attribute */
|
31
|
+
.highlight .nb { color: #0086B3 } /* Name.Builtin */
|
32
|
+
.highlight .nc { color: #445588; font-weight: bold } /* Name.Class */
|
33
|
+
.highlight .no { color: #008080 } /* Name.Constant */
|
34
|
+
.highlight .ni { color: #800080 } /* Name.Entity */
|
35
|
+
.highlight .ne { color: #990000; font-weight: bold } /* Name.Exception */
|
36
|
+
.highlight .nf { color: #990000; font-weight: bold } /* Name.Function */
|
37
|
+
.highlight .nn { color: #555555 } /* Name.Namespace */
|
38
|
+
.highlight .nt { color: #000080 } /* Name.Tag */
|
39
|
+
.highlight .nv { color: #008080 } /* Name.Variable */
|
40
|
+
.highlight .ow { font-weight: bold } /* Operator.Word */
|
41
|
+
.highlight .w { color: #bbbbbb } /* Text.Whitespace */
|
42
|
+
.highlight .mf { color: #009999 } /* Literal.Number.Float */
|
43
|
+
.highlight .mh { color: #009999 } /* Literal.Number.Hex */
|
44
|
+
.highlight .mi { color: #009999 } /* Literal.Number.Integer */
|
45
|
+
.highlight .mo { color: #009999 } /* Literal.Number.Oct */
|
46
|
+
.highlight .sb { color: #d14 } /* Literal.String.Backtick */
|
47
|
+
.highlight .sc { color: #d14 } /* Literal.String.Char */
|
48
|
+
.highlight .sd { color: #d14 } /* Literal.String.Doc */
|
49
|
+
.highlight .s2 { color: #d14 } /* Literal.String.Double */
|
50
|
+
.highlight .se { color: #d14 } /* Literal.String.Escape */
|
51
|
+
.highlight .sh { color: #d14 } /* Literal.String.Heredoc */
|
52
|
+
.highlight .si { color: #d14 } /* Literal.String.Interpol */
|
53
|
+
.highlight .sx { color: #d14 } /* Literal.String.Other */
|
54
|
+
.highlight .sr { color: #009926 } /* Literal.String.Regex */
|
55
|
+
.highlight .s1 { color: #d14 } /* Literal.String.Single */
|
56
|
+
.highlight .ss { color: #990073 } /* Literal.String.Symbol */
|
57
|
+
.highlight .bp { color: #999999 } /* Name.Builtin.Pseudo */
|
58
|
+
.highlight .vc { color: #008080 } /* Name.Variable.Class */
|
59
|
+
.highlight .vg { color: #008080 } /* Name.Variable.Global */
|
60
|
+
.highlight .vi { color: #008080 } /* Name.Variable.Instance */
|
61
|
+
.highlight .il { color: #009999 } /* Literal.Number.Integer.Long */
|
62
|
+
|
63
|
+
.type-csharp .highlight .k { color: #0000FF }
|
64
|
+
.type-csharp .highlight .kt { color: #0000FF }
|
65
|
+
.type-csharp .highlight .nf { color: #000000; font-weight: normal }
|
66
|
+
.type-csharp .highlight .nc { color: #2B91AF }
|
67
|
+
.type-csharp .highlight .nn { color: #000000 }
|
68
|
+
.type-csharp .highlight .s { color: #A31515 }
|
69
|
+
.type-csharp .highlight .sc { color: #A31515 }
|