surrounded 0.8.2 → 0.8.3

Sign up to get free protection for your applications and to get access to all the features.
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: