surrounded 0.8.2 → 0.8.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.travis.yml +1 -1
- data/README.md +25 -1
- data/lib/surrounded.rb +2 -0
- data/lib/surrounded/access_control.rb +12 -16
- data/lib/surrounded/context.rb +38 -17
- data/lib/surrounded/east_oriented.rb +1 -1
- data/lib/surrounded/version.rb +1 -1
- data/test/context_access_test.rb +1 -1
- data/test/example_threaded_test.rb +11 -17
- data/test/surrounded_context_test.rb +50 -3
- metadata +19 -19
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: fcd5a235a5131c97780460591911ce275b460907
|
4
|
+
data.tar.gz: e5662f4dfbfdae0f22f3832b7d259c7bb6daa9e0
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 6ee26aa514d524c218dde785998a696b90686e3d3952a094613920ff987e2da1abf387c1d6e44b114e8f5093299979a9d7c26f721956ab036a4a67e55a32bcfb
|
7
|
+
data.tar.gz: f16d747a27f0af4fdfe0b4b9376a87d3d1a2a026b91d6c8019fc89ca9256805a9ad6bc911405677b19c89d1089a5310f3fed375046d6734b5249b724ad5698f5
|
data/.travis.yml
CHANGED
data/README.md
CHANGED
@@ -340,7 +340,7 @@ Using the `role` method to define modules and classes takes care of the setup fo
|
|
340
340
|
|
341
341
|
```ruby
|
342
342
|
|
343
|
-
# this uses modules
|
343
|
+
# this uses modules which include Surrounded
|
344
344
|
role :source do
|
345
345
|
def transfer
|
346
346
|
self.balance -= amount
|
@@ -409,6 +409,30 @@ class MoneyTransfer
|
|
409
409
|
end
|
410
410
|
```
|
411
411
|
|
412
|
+
## Working with collections
|
413
|
+
|
414
|
+
If you want to use an Array of objects (for example) as a role player in your context,
|
415
|
+
you may do so. If you want each item in your collection to gain behavior, you merely need to
|
416
|
+
create a role for the items.
|
417
|
+
|
418
|
+
Surrounded will attempt to guess at the singular role name. For example, a role player named `members` would
|
419
|
+
be given the behaviors from a `Members` behavior module or class. Each item in your `members` collection
|
420
|
+
would be given behavior from a `Member` behavior module or class if you create one.
|
421
|
+
|
422
|
+
```ruby
|
423
|
+
class Organization
|
424
|
+
initialize :leader, :members
|
425
|
+
|
426
|
+
role :members do
|
427
|
+
# special behavior for the collection
|
428
|
+
end
|
429
|
+
|
430
|
+
role :member do
|
431
|
+
# special behavior to be applied to each member in the collection
|
432
|
+
end
|
433
|
+
end
|
434
|
+
```
|
435
|
+
|
412
436
|
## Policies for the application of role methods
|
413
437
|
|
414
438
|
There are 2 approaches to applying new behavior to your objects.
|
data/lib/surrounded.rb
CHANGED
@@ -16,6 +16,7 @@ module Surrounded
|
|
16
16
|
if accessor.role_player?(self)
|
17
17
|
surroundings.unshift(ctxt)
|
18
18
|
end
|
19
|
+
self
|
19
20
|
end
|
20
21
|
|
21
22
|
def remove_context(&block)
|
@@ -23,6 +24,7 @@ module Surrounded
|
|
23
24
|
if accessor.role_player?(self)
|
24
25
|
surroundings.shift
|
25
26
|
end
|
27
|
+
self
|
26
28
|
end
|
27
29
|
|
28
30
|
def surroundings
|
@@ -14,25 +14,18 @@ module Surrounded
|
|
14
14
|
define_access_method(name, &block)
|
15
15
|
end
|
16
16
|
end
|
17
|
+
alias_method :guard, :disallow
|
17
18
|
|
18
|
-
def
|
19
|
-
|
20
|
-
def #{name}
|
21
|
-
begin
|
22
|
-
apply_roles if __apply_role_policy == :trigger
|
23
|
-
|
24
|
-
method_restrictor = "disallow_#{name}?"
|
25
|
-
if self.respond_to?(method_restrictor, true) && self.send(method_restrictor)
|
26
|
-
raise ::#{self.to_s}::AccessError.new("access to #{self.name}##{name} is not allowed")
|
27
|
-
end
|
28
|
-
|
29
|
-
#{trigger_return_content(name)}
|
19
|
+
def trigger_return_content(name)
|
20
|
+
%{
|
30
21
|
|
31
|
-
|
32
|
-
|
33
|
-
|
22
|
+
method_restrictor = "disallow_#{name}?"
|
23
|
+
if self.respond_to?(method_restrictor, true) && self.send(method_restrictor)
|
24
|
+
raise ::#{self.to_s}::AccessError.new("access to #{self.name}##{name} is not allowed")
|
34
25
|
end
|
35
|
-
|
26
|
+
|
27
|
+
#{super}
|
28
|
+
}
|
36
29
|
end
|
37
30
|
|
38
31
|
def define_access_method(name, &block)
|
@@ -49,10 +42,13 @@ module Surrounded
|
|
49
42
|
end
|
50
43
|
|
51
44
|
module AccessMethods
|
45
|
+
# Return a Set of all defined triggers regardless of any disallow blocks
|
52
46
|
def all_triggers
|
53
47
|
self.class.triggers
|
54
48
|
end
|
55
49
|
|
50
|
+
# Return a Set of triggers which may be run according to any restrictions defined
|
51
|
+
# in disallow blocks.
|
56
52
|
def triggers
|
57
53
|
all_triggers.select {|name|
|
58
54
|
method_restrictor = "disallow_#{name}?"
|
data/lib/surrounded/context.rb
CHANGED
@@ -133,7 +133,9 @@ module Surrounded
|
|
133
133
|
role_type = type || default_role_type
|
134
134
|
if role_type == :module
|
135
135
|
mod_name = name.to_s.gsub(/(?:^|_)([a-z])/){ $1.upcase }
|
136
|
-
|
136
|
+
mod = Module.new(&block)
|
137
|
+
mod.send(:include, ::Surrounded)
|
138
|
+
private_const_set(mod_name, mod)
|
137
139
|
else
|
138
140
|
meth = method(role_type)
|
139
141
|
meth.call(name, &block)
|
@@ -162,17 +164,12 @@ module Surrounded
|
|
162
164
|
def trigger(*names, &block)
|
163
165
|
if block.nil?
|
164
166
|
names.each do |name|
|
165
|
-
|
167
|
+
convert_method_to_trigger(name)
|
166
168
|
end
|
167
169
|
else
|
168
170
|
name = names.first
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
private :"__trigger_#{name}"
|
173
|
-
store_trigger(name)
|
174
|
-
|
175
|
-
redo_method(name)
|
171
|
+
define_method(name, &block)
|
172
|
+
convert_method_to_trigger(name)
|
176
173
|
end
|
177
174
|
end
|
178
175
|
|
@@ -180,17 +177,17 @@ module Surrounded
|
|
180
177
|
@triggers.merge(names)
|
181
178
|
end
|
182
179
|
|
183
|
-
def
|
180
|
+
def convert_method_to_trigger(name)
|
184
181
|
unless triggers.include?(name) || name.nil?
|
185
182
|
alias_method :"__trigger_#{name}", :"#{name}"
|
186
183
|
private :"__trigger_#{name}"
|
187
184
|
remove_method :"#{name}"
|
188
|
-
|
185
|
+
define_trigger_wrap_method(name)
|
189
186
|
store_trigger(name)
|
190
187
|
end
|
191
188
|
end
|
192
189
|
|
193
|
-
def
|
190
|
+
def define_trigger_wrap_method(name)
|
194
191
|
class_eval %{
|
195
192
|
def #{name}
|
196
193
|
begin
|
@@ -248,6 +245,7 @@ module Surrounded
|
|
248
245
|
role_map.role_player?(obj)
|
249
246
|
end
|
250
247
|
|
248
|
+
# Return a Set of all defined triggers
|
251
249
|
def triggers
|
252
250
|
self.class.triggers
|
253
251
|
end
|
@@ -269,6 +267,15 @@ module Surrounded
|
|
269
267
|
def map_roles(role_object_array)
|
270
268
|
role_object_array.each do |role, object|
|
271
269
|
map_role(role, role_behavior_name(role), object)
|
270
|
+
|
271
|
+
singular_role_name = singularize_name(role)
|
272
|
+
singular_behavior_name = singularize_name(role_behavior_name(role))
|
273
|
+
|
274
|
+
if object.respond_to?(:each_with_index) && role_const_defined?(singular_behavior_name)
|
275
|
+
object.each_with_index do |item, index|
|
276
|
+
map_role(:"#{singular_role_name}_#{index + 1}", singular_behavior_name, item)
|
277
|
+
end
|
278
|
+
end
|
272
279
|
end
|
273
280
|
end
|
274
281
|
|
@@ -307,14 +314,13 @@ module Surrounded
|
|
307
314
|
|
308
315
|
def remove_interface(role, behavior, object)
|
309
316
|
remover_name = (module_removal_methods + unwrap_methods).find{|meth| object.respond_to?(meth) }
|
310
|
-
return object if !remover_name
|
311
|
-
|
312
317
|
object.send(:remove_context) do; end
|
313
|
-
role_player = object.method(remover_name).call
|
314
318
|
|
315
|
-
|
319
|
+
if remover_name
|
320
|
+
role_player = object.send(remover_name)
|
321
|
+
end
|
316
322
|
|
317
|
-
role_player
|
323
|
+
return role_player || object
|
318
324
|
end
|
319
325
|
|
320
326
|
def apply_roles
|
@@ -368,6 +374,21 @@ module Surrounded
|
|
368
374
|
def role_const_defined?(name)
|
369
375
|
self.class.const_defined?(name)
|
370
376
|
end
|
377
|
+
|
378
|
+
def singularize_name(name)
|
379
|
+
if name.respond_to?(:singularize)
|
380
|
+
name.singularize
|
381
|
+
else
|
382
|
+
# good enough for now but should be updated with better rules
|
383
|
+
name.to_s.tap do |string|
|
384
|
+
if string =~ /ies\z/
|
385
|
+
string.sub!(/ies\z/,'y')
|
386
|
+
elsif string =~ /s\z/
|
387
|
+
string.sub!(/s\z/,'')
|
388
|
+
end
|
389
|
+
end
|
390
|
+
end
|
391
|
+
end
|
371
392
|
end
|
372
393
|
end
|
373
394
|
end
|
data/lib/surrounded/version.rb
CHANGED
data/test/context_access_test.rb
CHANGED
@@ -3,28 +3,22 @@ require 'test_helper'
|
|
3
3
|
class ThreadedContext
|
4
4
|
extend Surrounded::Context
|
5
5
|
|
6
|
-
|
7
|
-
role_names = [:leader, :members]
|
8
|
-
role_players = [leader, members]
|
9
|
-
|
10
|
-
role_names.concat(members.map{|member| :"member_#{member.object_id}" })
|
11
|
-
role_players.concat(members)
|
12
|
-
|
13
|
-
map_roles(role_names.zip(role_players))
|
14
|
-
|
15
|
-
end
|
16
|
-
private_attr_reader :leader, :members
|
6
|
+
initialize :leader, :members
|
17
7
|
|
18
8
|
trigger :meet do
|
19
|
-
|
20
|
-
result << leader.greet
|
21
|
-
result << members.concurrent_map do |member|
|
22
|
-
result << member.greet
|
23
|
-
end
|
24
|
-
result.flatten.join(' ')
|
9
|
+
leader.welcome
|
25
10
|
end
|
26
11
|
|
27
12
|
module Leader
|
13
|
+
def welcome
|
14
|
+
result = []
|
15
|
+
result << leader.greet
|
16
|
+
result << members.concurrent_map do |member|
|
17
|
+
result << member.greet
|
18
|
+
end
|
19
|
+
result.flatten.join(' ')
|
20
|
+
end
|
21
|
+
|
28
22
|
def greet
|
29
23
|
"Hello everyone. I am #{name}"
|
30
24
|
end
|
@@ -173,12 +173,59 @@ describe Surrounded::Context, 'assigning roles' do
|
|
173
173
|
|
174
174
|
assert context.check_user_response
|
175
175
|
end
|
176
|
-
|
176
|
+
|
177
177
|
it 'allows usage of regular methods for triggers' do
|
178
178
|
assert context.regular_method_trigger
|
179
179
|
end
|
180
|
-
|
180
|
+
|
181
181
|
it 'ignores nil trigger names' do
|
182
182
|
assert context.class.send(:trigger)
|
183
183
|
end
|
184
|
-
end
|
184
|
+
end
|
185
|
+
|
186
|
+
class CollectionContext
|
187
|
+
extend Surrounded::Context
|
188
|
+
|
189
|
+
initialize :members, :others
|
190
|
+
|
191
|
+
trigger :get_members_count do
|
192
|
+
members.member_count
|
193
|
+
end
|
194
|
+
|
195
|
+
trigger :get_member_show do
|
196
|
+
members.map(&:show).join(', ')
|
197
|
+
end
|
198
|
+
|
199
|
+
role :members do
|
200
|
+
def member_count
|
201
|
+
size
|
202
|
+
end
|
203
|
+
end
|
204
|
+
|
205
|
+
role :member do
|
206
|
+
def show
|
207
|
+
"member show"
|
208
|
+
end
|
209
|
+
end
|
210
|
+
|
211
|
+
end
|
212
|
+
|
213
|
+
describe Surrounded::Context, 'auto-assigning roles for collections' do
|
214
|
+
let(:member_one){ User.new('Jim') }
|
215
|
+
let(:member_two){ User.new('Amy') }
|
216
|
+
let(:members){ [member_one, member_two] }
|
217
|
+
|
218
|
+
let(:other_one){ User.new('Guille') }
|
219
|
+
let(:other_two){ User.new('Jason') }
|
220
|
+
let(:others){ [other_one, other_two] }
|
221
|
+
|
222
|
+
let(:context){ CollectionContext.new(members, others) }
|
223
|
+
|
224
|
+
it 'assigns the collection role to collections' do
|
225
|
+
assert_equal members.size, context.get_members_count
|
226
|
+
end
|
227
|
+
|
228
|
+
it 'assigns a defined role to each item in a role player collection' do
|
229
|
+
assert_equal "member show, member show", context.get_member_show
|
230
|
+
end
|
231
|
+
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.3
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- '''Jim Gay'''
|
8
|
-
autorequire:
|
8
|
+
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2014-
|
11
|
+
date: 2014-03-10 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: triad
|
15
|
-
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
16
|
requirements:
|
17
17
|
- - ~>
|
18
18
|
- !ruby/object:Gem::Version
|
19
19
|
version: 0.1.2
|
20
|
-
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
21
23
|
requirements:
|
22
24
|
- - ~>
|
23
25
|
- !ruby/object:Gem::Version
|
24
26
|
version: 0.1.2
|
25
|
-
prerelease: false
|
26
|
-
type: :runtime
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
28
|
name: bundler
|
29
|
-
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
30
|
requirements:
|
31
31
|
- - ~>
|
32
32
|
- !ruby/object:Gem::Version
|
33
33
|
version: '1.3'
|
34
|
-
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
35
37
|
requirements:
|
36
38
|
- - ~>
|
37
39
|
- !ruby/object:Gem::Version
|
38
40
|
version: '1.3'
|
39
|
-
prerelease: false
|
40
|
-
type: :development
|
41
41
|
- !ruby/object:Gem::Dependency
|
42
42
|
name: rake
|
43
|
-
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
44
|
requirements:
|
45
45
|
- - '>='
|
46
46
|
- !ruby/object:Gem::Version
|
47
47
|
version: '0'
|
48
|
-
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
49
51
|
requirements:
|
50
52
|
- - '>='
|
51
53
|
- !ruby/object:Gem::Version
|
52
54
|
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
|
@@ -91,7 +91,7 @@ homepage: http://github.com/saturnflyer/surrounded
|
|
91
91
|
licenses:
|
92
92
|
- MIT
|
93
93
|
metadata: {}
|
94
|
-
post_install_message:
|
94
|
+
post_install_message:
|
95
95
|
rdoc_options: []
|
96
96
|
require_paths:
|
97
97
|
- lib
|
@@ -106,9 +106,9 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
106
106
|
- !ruby/object:Gem::Version
|
107
107
|
version: '0'
|
108
108
|
requirements: []
|
109
|
-
rubyforge_project:
|
110
|
-
rubygems_version: 2.
|
111
|
-
signing_key:
|
109
|
+
rubyforge_project:
|
110
|
+
rubygems_version: 2.0.14
|
111
|
+
signing_key:
|
112
112
|
specification_version: 4
|
113
113
|
summary: Create encapsulated environments for your objects.
|
114
114
|
test_files:
|