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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 8a0524827a23eeb3aa9829988d8d5bc7773e81ca
4
- data.tar.gz: ad49086b9e50454fbfb31c143d5428d52d46c0f9
3
+ metadata.gz: fcd5a235a5131c97780460591911ce275b460907
4
+ data.tar.gz: e5662f4dfbfdae0f22f3832b7d259c7bb6daa9e0
5
5
  SHA512:
6
- metadata.gz: d84eaf1f7907b2b6c6a80e585721104916142f47fb79b4d5ccee6abdd6516868b7c08463234a38ea0d5f713914c11facef87abff0434ff3b9dc140e03da22100
7
- data.tar.gz: eeb0bd64cf19f0d7e8ecd17df70d77f2ecc4e193ec95f952f95fda2f504e1fd8182beb92c953e6a4ab0e64475795b38f6c253bab820a705bb61901131d38db10
6
+ metadata.gz: 6ee26aa514d524c218dde785998a696b90686e3d3952a094613920ff987e2da1abf387c1d6e44b114e8f5093299979a9d7c26f721956ab036a4a67e55a32bcfb
7
+ data.tar.gz: f16d747a27f0af4fdfe0b4b9376a87d3d1a2a026b91d6c8019fc89ca9256805a9ad6bc911405677b19c89d1089a5310f3fed375046d6734b5249b724ad5698f5
data/.travis.yml CHANGED
@@ -2,7 +2,7 @@ language: ruby
2
2
  rvm:
3
3
  - 1.9.3
4
4
  - 2.0.0
5
- - 2.1.0
5
+ - 2.1.1
6
6
  - jruby-19mode # JRuby in 1.9 mode
7
7
  - ruby-head
8
8
  - jruby-head
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 redo_method(name)
19
- class_eval %{
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
- ensure
32
- remove_roles if __apply_role_policy == :trigger
33
- end
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
- }, __FILE__, __LINE__
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}?"
@@ -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
- private_const_set(mod_name, Module.new(&block))
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
- define_trigger_method(name, &block)
167
+ convert_method_to_trigger(name)
166
168
  end
167
169
  else
168
170
  name = names.first
169
-
170
- define_method(:"__trigger_#{name}", &block)
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 define_trigger_method(name, &block)
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
- redo_method(name)
185
+ define_trigger_wrap_method(name)
189
186
  store_trigger(name)
190
187
  end
191
188
  end
192
189
 
193
- def redo_method(name)
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
- map_role(role, role_module_basename(behavior), role_player) if behavior
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
@@ -4,7 +4,7 @@ module Surrounded
4
4
  # not be asked for information.
5
5
  def trigger_return_content(name)
6
6
  %{
7
- self.send("__trigger_#{name}")
7
+ #{super}
8
8
 
9
9
  self
10
10
  }
@@ -1,3 +1,3 @@
1
1
  module Surrounded
2
- VERSION = "0.8.2"
2
+ VERSION = "0.8.3"
3
3
  end
@@ -11,7 +11,7 @@ class FilteredContext
11
11
  'ready'
12
12
  end
13
13
 
14
- disallow :if_ready do
14
+ guard :if_ready do
15
15
  user.name != 'Amy'
16
16
  end
17
17
 
@@ -3,28 +3,22 @@ require 'test_helper'
3
3
  class ThreadedContext
4
4
  extend Surrounded::Context
5
5
 
6
- def initialize(leader, members)
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
- result = []
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.2
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-02-09 00:00:00.000000000 Z
11
+ date: 2014-03-10 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: triad
15
- version_requirements: !ruby/object:Gem::Requirement
15
+ requirement: !ruby/object:Gem::Requirement
16
16
  requirements:
17
17
  - - ~>
18
18
  - !ruby/object:Gem::Version
19
19
  version: 0.1.2
20
- requirement: !ruby/object:Gem::Requirement
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
- version_requirements: !ruby/object:Gem::Requirement
29
+ requirement: !ruby/object:Gem::Requirement
30
30
  requirements:
31
31
  - - ~>
32
32
  - !ruby/object:Gem::Version
33
33
  version: '1.3'
34
- requirement: !ruby/object:Gem::Requirement
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
- version_requirements: !ruby/object:Gem::Requirement
43
+ requirement: !ruby/object:Gem::Requirement
44
44
  requirements:
45
45
  - - '>='
46
46
  - !ruby/object:Gem::Version
47
47
  version: '0'
48
- requirement: !ruby/object:Gem::Requirement
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.1.9
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: