surrounded 0.8.1 → 0.8.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/Gemfile +1 -0
- data/README.md +26 -11
- data/lib/surrounded/access_control.rb +5 -2
- data/lib/surrounded/context.rb +10 -2
- data/lib/surrounded/east_oriented.rb +13 -0
- data/lib/surrounded/version.rb +1 -1
- data/test/context_access_test.rb +11 -2
- data/test/east_oriented_triggers_test.rb +36 -0
- metadata +34 -31
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 8a0524827a23eeb3aa9829988d8d5bc7773e81ca
|
4
|
+
data.tar.gz: ad49086b9e50454fbfb31c143d5428d52d46c0f9
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: d84eaf1f7907b2b6c6a80e585721104916142f47fb79b4d5ccee6abdd6516868b7c08463234a38ea0d5f713914c11facef87abff0434ff3b9dc140e03da22100
|
7
|
+
data.tar.gz: eeb0bd64cf19f0d7e8ecd17df70d77f2ecc4e193ec95f952f95fda2f504e1fd8182beb92c953e6a4ab0e64475795b38f6c253bab820a705bb61901131d38db10
|
data/Gemfile
CHANGED
data/README.md
CHANGED
@@ -14,7 +14,7 @@ The purpose of this library is to clear away the details of getting things setup
|
|
14
14
|
There are two main parts to this library.
|
15
15
|
|
16
16
|
1. `Surrounded` gives objects an implicit awareness of other objects in their environments.
|
17
|
-
2. `Surrounded::Context` helps you create objects which encapsulate other objects. These *are* the environments.
|
17
|
+
2. `Surrounded::Context` helps you create objects which encapsulate other objects **and** their behavior. These *are* the environments.
|
18
18
|
|
19
19
|
First, take a look at creating contexts. This is where you'll spend most of your time.
|
20
20
|
|
@@ -307,7 +307,24 @@ Alternatively, if you just want to define your own methods without the DSL using
|
|
307
307
|
|
308
308
|
In fact, that's exactly what happens with the `disallow` keyword. After using it here, we'd have a `disallow_shove_it?` method defined.
|
309
309
|
|
310
|
-
If you call the disallowed trigger directly, you'll raise a `
|
310
|
+
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.
|
311
|
+
|
312
|
+
## Restricting return values
|
313
|
+
|
314
|
+
_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.
|
315
|
+
|
316
|
+
Here's how you enforce it:
|
317
|
+
|
318
|
+
```ruby
|
319
|
+
class MyEnvironment
|
320
|
+
extend Surrounded::Context
|
321
|
+
east_oriented_triggers
|
322
|
+
end
|
323
|
+
```
|
324
|
+
|
325
|
+
That's it.
|
326
|
+
|
327
|
+
With that change, any trigger you define will execute the block you provide and return `self`, being the instance of the context.
|
311
328
|
|
312
329
|
## Where roles exist
|
313
330
|
|
@@ -472,15 +489,9 @@ class ActiviatingAccount
|
|
472
489
|
# pass an array of arrays with role name symbol and the object for that role
|
473
490
|
map_roles([[:activator, activator],[:account, account]])
|
474
491
|
end
|
475
|
-
|
476
|
-
#
|
477
|
-
|
478
|
-
def preinitialize
|
479
|
-
# to happen before any role mapping
|
480
|
-
end
|
481
|
-
def postinitialize
|
482
|
-
# to happen after any role mapping
|
483
|
-
end
|
492
|
+
# these also must be done if you create your own initialize method.
|
493
|
+
# this is a shortcut for using attr_reader and private
|
494
|
+
private_attr_reader :activator, :account
|
484
495
|
|
485
496
|
role :activator do # module by default
|
486
497
|
def some_behavior; end
|
@@ -549,6 +560,10 @@ class ActiviatingAccount
|
|
549
560
|
instance.some_trigger_method
|
550
561
|
end
|
551
562
|
|
563
|
+
# Set triggers to always return the context object
|
564
|
+
# so you can enforce East-oriented style or Tell, Don't Ask
|
565
|
+
east_oriented_triggers
|
566
|
+
|
552
567
|
end
|
553
568
|
```
|
554
569
|
|
@@ -2,6 +2,9 @@ module Surrounded
|
|
2
2
|
module AccessControl
|
3
3
|
def self.extended(base)
|
4
4
|
base.send(:include, AccessMethods)
|
5
|
+
unless defined?(base::AccessError)
|
6
|
+
base.const_set(:AccessError, Class.new(::Surrounded::Context::AccessError))
|
7
|
+
end
|
5
8
|
end
|
6
9
|
|
7
10
|
private
|
@@ -20,10 +23,10 @@ module Surrounded
|
|
20
23
|
|
21
24
|
method_restrictor = "disallow_#{name}?"
|
22
25
|
if self.respond_to?(method_restrictor, true) && self.send(method_restrictor)
|
23
|
-
raise ::
|
26
|
+
raise ::#{self.to_s}::AccessError.new("access to #{self.name}##{name} is not allowed")
|
24
27
|
end
|
25
28
|
|
26
|
-
|
29
|
+
#{trigger_return_content(name)}
|
27
30
|
|
28
31
|
ensure
|
29
32
|
remove_roles if __apply_role_policy == :trigger
|
data/lib/surrounded/context.rb
CHANGED
@@ -2,6 +2,7 @@ require 'set'
|
|
2
2
|
require 'surrounded/context/role_map'
|
3
3
|
require 'surrounded/access_control'
|
4
4
|
require 'surrounded/shortcuts'
|
5
|
+
require 'surrounded/east_oriented'
|
5
6
|
|
6
7
|
# Some features are only available in versions of Ruby
|
7
8
|
# where this method is true
|
@@ -62,7 +63,10 @@ module Surrounded
|
|
62
63
|
def protect_triggers; self.extend(::Surrounded::AccessControl); end
|
63
64
|
|
64
65
|
# Automatically create class methods for each trigger method.
|
65
|
-
def shortcut_triggers; self.extend(::Surrounded::Shortcuts);
|
66
|
+
def shortcut_triggers; self.extend(::Surrounded::Shortcuts); end
|
67
|
+
|
68
|
+
# Automatically return the context object from trigger methods.
|
69
|
+
def east_oriented_triggers; self.extend(::Surrounded::EastOriented); end
|
66
70
|
|
67
71
|
def default_role_type
|
68
72
|
@default_role_type ||= Surrounded::Context.default_role_type
|
@@ -192,7 +196,7 @@ module Surrounded
|
|
192
196
|
begin
|
193
197
|
apply_roles if __apply_role_policy == :trigger
|
194
198
|
|
195
|
-
|
199
|
+
#{trigger_return_content(name)}
|
196
200
|
|
197
201
|
ensure
|
198
202
|
remove_roles if __apply_role_policy == :trigger
|
@@ -201,6 +205,10 @@ module Surrounded
|
|
201
205
|
}, __FILE__, __LINE__
|
202
206
|
end
|
203
207
|
|
208
|
+
def trigger_return_content(name)
|
209
|
+
%{self.send("__trigger_#{name}")}
|
210
|
+
end
|
211
|
+
|
204
212
|
# === Utility shortcuts
|
205
213
|
|
206
214
|
# Set a named constant and make it private
|
data/lib/surrounded/version.rb
CHANGED
data/test/context_access_test.rb
CHANGED
@@ -45,13 +45,22 @@ describe Surrounded::Context, 'access control' do
|
|
45
45
|
refute context.triggers.include?(:if_ready)
|
46
46
|
end
|
47
47
|
|
48
|
-
it 'raises
|
49
|
-
error = assert_raises(::
|
48
|
+
it 'raises error specific to the context class when trigger method not allowed' do
|
49
|
+
error = assert_raises(::FilteredContext::AccessError){
|
50
50
|
context.if_ready
|
51
51
|
}
|
52
52
|
assert_match(/access to FilteredContext#if_ready is not allowed/i, error.message)
|
53
53
|
end
|
54
54
|
|
55
|
+
it 'supports rescuing from Surrounded defined error when trigger method not allowed' do
|
56
|
+
begin
|
57
|
+
context.if_ready
|
58
|
+
rescue ::Surrounded::Context::AccessError => error
|
59
|
+
assert "rescued!"
|
60
|
+
end
|
61
|
+
assert_match(/access to FilteredContext#if_ready is not allowed/i, error.message)
|
62
|
+
end
|
63
|
+
|
55
64
|
it 'applies roles in disallow blocks' do
|
56
65
|
assert_equal 'special user method', context.disallow_check_disallow_behavior?
|
57
66
|
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
|
3
|
+
class EastTestContext
|
4
|
+
extend Surrounded::Context
|
5
|
+
east_oriented_triggers
|
6
|
+
|
7
|
+
initialize :user, :other_user
|
8
|
+
|
9
|
+
trigger :ask? do
|
10
|
+
"asking a question..."
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
describe Surrounded::Context, '.east_oriented_triggers' do
|
15
|
+
let(:user){ User.new("Jim") }
|
16
|
+
let(:other_user){ User.new("Guille") }
|
17
|
+
let(:context){ EastTestContext.new(user, other_user) }
|
18
|
+
|
19
|
+
it 'returns the context object from trigger methods' do
|
20
|
+
assert_equal context, context.ask?
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
describe Surrounded::Context, '.east_oriented_triggers with protect_triggers' do
|
25
|
+
let(:user){ User.new("Jim") }
|
26
|
+
let(:other_user){ User.new("Guille") }
|
27
|
+
let(:context){
|
28
|
+
ctxt = EastTestContext.new(user, other_user)
|
29
|
+
ctxt.singleton_class.send(:protect_triggers)
|
30
|
+
ctxt
|
31
|
+
}
|
32
|
+
|
33
|
+
it 'returns the context object from trigger methods' do
|
34
|
+
assert_equal context, context.ask?
|
35
|
+
end
|
36
|
+
end
|
metadata
CHANGED
@@ -1,57 +1,57 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: surrounded
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.8.
|
4
|
+
version: 0.8.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
|
-
-
|
8
|
-
autorequire:
|
7
|
+
- '''Jim Gay'''
|
8
|
+
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2014-
|
11
|
+
date: 2014-02-09 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: triad
|
15
|
-
|
15
|
+
version_requirements: !ruby/object:Gem::Requirement
|
16
16
|
requirements:
|
17
|
-
- -
|
17
|
+
- - ~>
|
18
18
|
- !ruby/object:Gem::Version
|
19
19
|
version: 0.1.2
|
20
|
-
|
21
|
-
prerelease: false
|
22
|
-
version_requirements: !ruby/object:Gem::Requirement
|
20
|
+
requirement: !ruby/object:Gem::Requirement
|
23
21
|
requirements:
|
24
|
-
- -
|
22
|
+
- - ~>
|
25
23
|
- !ruby/object:Gem::Version
|
26
24
|
version: 0.1.2
|
25
|
+
prerelease: false
|
26
|
+
type: :runtime
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
28
|
name: bundler
|
29
|
-
|
29
|
+
version_requirements: !ruby/object:Gem::Requirement
|
30
30
|
requirements:
|
31
|
-
- -
|
31
|
+
- - ~>
|
32
32
|
- !ruby/object:Gem::Version
|
33
33
|
version: '1.3'
|
34
|
-
|
35
|
-
prerelease: false
|
36
|
-
version_requirements: !ruby/object:Gem::Requirement
|
34
|
+
requirement: !ruby/object:Gem::Requirement
|
37
35
|
requirements:
|
38
|
-
- -
|
36
|
+
- - ~>
|
39
37
|
- !ruby/object:Gem::Version
|
40
38
|
version: '1.3'
|
39
|
+
prerelease: false
|
40
|
+
type: :development
|
41
41
|
- !ruby/object:Gem::Dependency
|
42
42
|
name: rake
|
43
|
-
|
43
|
+
version_requirements: !ruby/object:Gem::Requirement
|
44
44
|
requirements:
|
45
|
-
- -
|
45
|
+
- - '>='
|
46
46
|
- !ruby/object:Gem::Version
|
47
47
|
version: '0'
|
48
|
-
|
49
|
-
prerelease: false
|
50
|
-
version_requirements: !ruby/object:Gem::Requirement
|
48
|
+
requirement: !ruby/object:Gem::Requirement
|
51
49
|
requirements:
|
52
|
-
- -
|
50
|
+
- - '>='
|
53
51
|
- !ruby/object:Gem::Version
|
54
52
|
version: '0'
|
53
|
+
prerelease: false
|
54
|
+
type: :development
|
55
55
|
description: Gives an object implicit access to other objects in it's environment.
|
56
56
|
email:
|
57
57
|
- jim@saturnflyer.com
|
@@ -59,9 +59,9 @@ executables: []
|
|
59
59
|
extensions: []
|
60
60
|
extra_rdoc_files: []
|
61
61
|
files:
|
62
|
-
-
|
63
|
-
-
|
64
|
-
-
|
62
|
+
- .gitignore
|
63
|
+
- .simplecov
|
64
|
+
- .travis.yml
|
65
65
|
- Gemfile
|
66
66
|
- LICENSE.txt
|
67
67
|
- README.md
|
@@ -73,11 +73,13 @@ files:
|
|
73
73
|
- lib/surrounded/context/negotiator.rb
|
74
74
|
- lib/surrounded/context/role_map.rb
|
75
75
|
- lib/surrounded/context_errors.rb
|
76
|
+
- lib/surrounded/east_oriented.rb
|
76
77
|
- lib/surrounded/shortcuts.rb
|
77
78
|
- lib/surrounded/version.rb
|
78
79
|
- surrounded.gemspec
|
79
80
|
- test/context_access_test.rb
|
80
81
|
- test/context_shortcuts_test.rb
|
82
|
+
- test/east_oriented_triggers_test.rb
|
81
83
|
- test/example_proxy_test.rb
|
82
84
|
- test/example_threaded_test.rb
|
83
85
|
- test/example_wrapper_test.rb
|
@@ -89,29 +91,30 @@ homepage: http://github.com/saturnflyer/surrounded
|
|
89
91
|
licenses:
|
90
92
|
- MIT
|
91
93
|
metadata: {}
|
92
|
-
post_install_message:
|
94
|
+
post_install_message:
|
93
95
|
rdoc_options: []
|
94
96
|
require_paths:
|
95
97
|
- lib
|
96
98
|
required_ruby_version: !ruby/object:Gem::Requirement
|
97
99
|
requirements:
|
98
|
-
- -
|
100
|
+
- - '>='
|
99
101
|
- !ruby/object:Gem::Version
|
100
102
|
version: '0'
|
101
103
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
102
104
|
requirements:
|
103
|
-
- -
|
105
|
+
- - '>='
|
104
106
|
- !ruby/object:Gem::Version
|
105
107
|
version: '0'
|
106
108
|
requirements: []
|
107
|
-
rubyforge_project:
|
108
|
-
rubygems_version: 2.
|
109
|
-
signing_key:
|
109
|
+
rubyforge_project:
|
110
|
+
rubygems_version: 2.1.9
|
111
|
+
signing_key:
|
110
112
|
specification_version: 4
|
111
113
|
summary: Create encapsulated environments for your objects.
|
112
114
|
test_files:
|
113
115
|
- test/context_access_test.rb
|
114
116
|
- test/context_shortcuts_test.rb
|
117
|
+
- test/east_oriented_triggers_test.rb
|
115
118
|
- test/example_proxy_test.rb
|
116
119
|
- test/example_threaded_test.rb
|
117
120
|
- test/example_wrapper_test.rb
|