surrounded 0.9.8 → 0.9.9

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: f5e41776a1619ac88e5a77857ae85f6d0ef7bbf1
4
- data.tar.gz: 2e39e542b1955af150bf148dc4b15fd29bd7dd46
3
+ metadata.gz: 676d57f548d17fbf0d9112208472938b7c5a2e82
4
+ data.tar.gz: 830bf96b8114f786840315b24fba5f90450be813
5
5
  SHA512:
6
- metadata.gz: 2bbac0d9d89de2880aee0c54b8916a37d7862d4071f0d9a24f9e93cc7df53733fc9b9e206fbe7552736ef0c90f1320e728fe0990deeda8a03e5921b6080ccc59
7
- data.tar.gz: 94765d82ed5d64e8d2318ddb53cafd2ad633e3288157df9528df6a40687d04dda66f50b432572a1dc9f361bb73f0549e7d5453b9f5872ab69c4a5c2f6f8aeeab
6
+ metadata.gz: 1bc24e149d0fefd9961ea08c92a01390cbdc24d94a42fa6a06e542a219838572f3c75fa8e65ec6e54324236a53950461e4b81afd7e732a0a6765220e4c5a27d6
7
+ data.tar.gz: dd4ee61d04717d8418e011e6421031196bada55ae25d6fb04e24c9913fc06ccc2c199a443c4f554618f3298ef6e7319d81467ee69e43b135cf7da6aa2214f0cd
data/README.md CHANGED
@@ -475,7 +475,7 @@ This will allow you to write methods like you normally would. They are aliased i
475
475
 
476
476
  This works like Ruby's `public`,`protected`, and `private` keywords in that you can send symbols of method names to it. But `trigger` does not alter the parsing of the document like those core keywords do. In other words, you can't merely type `trigger` on one line, and have methods added afterward be treated as trigger methods.
477
477
 
478
- ## Access Control for Triggers
478
+ ## Access Control / Permissions for Triggers
479
479
 
480
480
  If you decide to build a user interface from the available triggers, you'll find you need to know what triggers are available.
481
481
 
@@ -647,6 +647,35 @@ context = Employment.new(current_user, the_boss)
647
647
  context.rebind(employee: another_user, boss: someone_else) # same context, new players
648
648
  ```
649
649
 
650
+ ## Background Processing
651
+
652
+ While there's no specific support for background processing, your context objects make it easy for you to add your own by remembering what arguments were provided during initialization.
653
+
654
+ When you initialize a context, it will keep track of the parameters and their matching arguments in a private hash called `initializer_arguments`. This allows you to write methods to create a context object and have itself sent to a background processor.
655
+
656
+ ```ruby
657
+ class ExpensiveCalculation
658
+ extend Surrounded::Context
659
+
660
+ initialize :leader, :members
661
+
662
+ def send_to_background(trigger_method)
663
+ background_arguments = initializer_arguments.merge(trigger: trigger_method)
664
+ BackgroundProcessor.enqueue(self.class.name, **background_arguments)
665
+ end
666
+
667
+ class BackgroundProcessor
668
+ def perform(**args)
669
+ trigger_name = args.delete(:trigger)
670
+ job_class.new(args).send(trigger_name)
671
+ end
672
+ end
673
+ end
674
+ ExpensiveCalculation.new(some_object, some_collection).send_to_background(:do_expensive_calculation)
675
+ ```
676
+
677
+ The above example is merely pseudo-code to show how `initializer_arguments` can be used. Customize it according to your own needs.
678
+
650
679
  ## Overview in code
651
680
 
652
681
  Here's a view of the possibilities in code.
@@ -36,12 +36,14 @@ module Surrounded
36
36
  line = __LINE__; mod.class_eval %{
37
37
  def initialize(#{params})
38
38
  @role_map = role_mapper_class.new
39
- map_roles(#{setup_args.to_s}.zip([#{setup_args.join(',')}]))
39
+ @initializer_arguments = Hash[#{setup_args.to_s}.zip([#{setup_args.join(',')}])]
40
+ map_roles(@initializer_arguments)
40
41
  self.class.apply_initializer_block(self)
41
42
  end
42
43
  }, __FILE__, line
43
44
  const_set("ContextInitializer", mod)
44
45
  include mod
46
+ private_attr_reader :initializer_arguments
45
47
  end
46
48
  end
47
49
  end
@@ -1,5 +1,5 @@
1
1
  module Surrounded
2
- VERSION = "0.9.8"
2
+ VERSION = "0.9.9"
3
3
 
4
4
  def self.version
5
5
  VERSION
@@ -0,0 +1,7 @@
1
+ require 'test_helper'
2
+
3
+ require 'casting'
4
+ class CastingUser < User
5
+ include Casting::Client
6
+ delegate_missing_methods
7
+ end
@@ -0,0 +1,51 @@
1
+ require 'test_helper'
2
+
3
+ class CollectionContext
4
+ extend Surrounded::Context
5
+
6
+ initialize :members, :others
7
+
8
+ trigger :get_members_count do
9
+ members.member_count
10
+ end
11
+
12
+ trigger :get_member_show do
13
+ members.map(&:show).join(', ')
14
+ end
15
+
16
+ role :members do
17
+ def member_count
18
+ size
19
+ end
20
+ end
21
+
22
+ role :member do
23
+ def show
24
+ "member show"
25
+ end
26
+ end
27
+
28
+ role :others do; end
29
+ role :other do; end
30
+
31
+ end
32
+
33
+ describe Surrounded::Context, 'auto-assigning roles for collections' do
34
+ let(:member_one){ User.new('Jim') }
35
+ let(:member_two){ User.new('Amy') }
36
+ let(:members){ [member_one, member_two] }
37
+
38
+ let(:other_one){ User.new('Guille') }
39
+ let(:other_two){ User.new('Jason') }
40
+ let(:others){ [other_one, other_two] }
41
+
42
+ let(:context){ CollectionContext.new(members, others) }
43
+
44
+ it 'assigns the collection role to collections' do
45
+ assert_equal members.size, context.get_members_count
46
+ end
47
+
48
+ it 'assigns a defined role to each item in a role player collection' do
49
+ assert_equal "member show, member show", context.get_member_show
50
+ end
51
+ end
@@ -0,0 +1,22 @@
1
+ require 'test_helper'
2
+
3
+ describe Surrounded::Context, 'reusing context object' do
4
+ let(:user){ User.new("Jim") }
5
+ let(:other_user){ User.new("Guille") }
6
+ let(:context){ TestContext.new(user, other_user) }
7
+
8
+ it 'allows rebinding new players' do
9
+ expect(context.access_other_object).must_equal 'Guille'
10
+ context.rebind(user: User.new('Amy'), other_user: User.new('Elizabeth'))
11
+ expect(context.access_other_object).must_equal 'Elizabeth'
12
+ end
13
+
14
+ it 'clears internal storage when rebinding' do
15
+ originals = context.instance_variables.map{|var| context.instance_variable_get(var) }
16
+ context.rebind(user: User.new('Amy'), other_user: User.new('Elizabeth'))
17
+ new_ivars = context.instance_variables.map{|var| context.instance_variable_get(var) }
18
+ originals.zip(new_ivars).each do |original_ivar, new_ivar|
19
+ expect(original_ivar).wont_equal new_ivar
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,58 @@
1
+ require 'test_helper'
2
+
3
+ class InitContext
4
+ extend Surrounded::Context
5
+
6
+ initialize(:user, :other_user) do
7
+ @defined_by_initializer_block = 'yup'
8
+ end
9
+ end
10
+
11
+ describe Surrounded::Context, '.initialize' do
12
+ it 'defines an initialize method accepting the same arguments' do
13
+ assert_equal 2, InitContext.instance_method(:initialize).arity
14
+ end
15
+
16
+ it 'applies a provided block to the instance' do
17
+ context = InitContext.new(User.new('Jim'), User.new('Amy'))
18
+ assert_equal 'yup', context.instance_variable_get(:@defined_by_initializer_block)
19
+ end
20
+
21
+ it 'keeps track of the original initialize arguments' do
22
+ jim = User.new('Jim')
23
+ amy = User.new('Amy')
24
+ context = InitContext.new(jim, amy)
25
+ tracked = context.send(:initializer_arguments)
26
+ assert_equal jim, tracked[:user]
27
+ assert_equal amy, tracked[:other_user]
28
+ end
29
+ end
30
+
31
+ begin
32
+ class Keyworder
33
+ extend Surrounded::Context
34
+
35
+ keyword_initialize :this, :that do
36
+ self.instance_variable_set(:@defined_by_initializer_block, 'yes')
37
+ end
38
+ end
39
+
40
+ describe Surrounded::Context, 'keyword initializers' do
41
+ it 'works with keyword arguments' do
42
+ assert Keyworder.new(this: User.new('Jim'), that: User.new('Guille'))
43
+ end
44
+
45
+ it 'raises errors with missing keywords' do
46
+ err = assert_raises(ArgumentError){
47
+ Keyworder.new(this: User.new('Amy'))
48
+ }
49
+ assert_match(/missing keyword: that/, err.message)
50
+ end
51
+
52
+ it 'evaluates a given block' do
53
+ assert_equal 'yes', Keyworder.new(this: User.new('Jim'), that: User.new('Guille')).instance_variable_get(:@defined_by_initializer_block)
54
+ end
55
+ end
56
+ rescue SyntaxError
57
+ STDOUT.puts "No support for keywords"
58
+ end
@@ -0,0 +1,27 @@
1
+ require 'test_helper'
2
+
3
+ class BareObjectContext
4
+ extend Surrounded::Context
5
+
6
+ def initialize(number, string, user)
7
+ map_roles(:number => number, :string => string, :user => user)
8
+ end
9
+ private_attr_reader :number, :string, :user
10
+
11
+ role :user do
12
+ def output
13
+ [number.to_s, string, name].join(' - ')
14
+ end
15
+ end
16
+
17
+ trigger :output do
18
+ user.output
19
+ end
20
+ end
21
+
22
+ describe Surrounded::Context, 'skips affecting non-surrounded objects' do
23
+ it 'works with non-surrounded objects' do
24
+ context = BareObjectContext.new(123,'hello', User.new('Jim'))
25
+ assert_equal '123 - hello - Jim', context.output
26
+ end
27
+ end
@@ -97,18 +97,10 @@ describe Surrounded::Context, '#role?' do
97
97
  end
98
98
  end
99
99
 
100
- require 'casting'
101
- class CastingUser < User
102
- include Casting::Client
103
- delegate_missing_methods
104
- end
105
-
106
100
  class RoleAssignmentContext
107
101
  extend Surrounded::Context
108
102
 
109
- initialize(:user, :other_user) do
110
- self.instance_variable_set(:@defined_by_initializer_block, 'yup')
111
- end
103
+ initialize(:user, :other_user)
112
104
 
113
105
  def user_ancestors
114
106
  user.singleton_class.ancestors
@@ -152,12 +144,6 @@ class IgnoreExternalConstantsContext
152
144
  end
153
145
  end
154
146
 
155
- describe Surrounded::Context, '.initialize' do
156
- it 'defines an initialize method accepting the same arguments' do
157
- assert_equal 2, RoleAssignmentContext.instance_method(:initialize).arity
158
- end
159
- end
160
-
161
147
  class ClassRoleAssignmentContext
162
148
  extend Surrounded::Context
163
149
 
@@ -209,134 +195,4 @@ describe Surrounded::Context, 'assigning roles' do
209
195
  context = IgnoreExternalConstantsContext.new(user, special, other)
210
196
  assert_equal User, context.check_special
211
197
  end
212
-
213
- it 'applies a provided block to the instance' do
214
- assert_equal 'yup', context.instance_variable_get(:@defined_by_initializer_block)
215
- end
216
- end
217
-
218
- class BareObjectContext
219
- extend Surrounded::Context
220
-
221
- def initialize(number, string, user)
222
- map_roles(:number => number, :string => string, :user => user)
223
- end
224
- private_attr_reader :number, :string, :user
225
-
226
- role :user do
227
- def output
228
- [number.to_s, string, name].join(' - ')
229
- end
230
- end
231
-
232
- trigger :output do
233
- user.output
234
- end
235
- end
236
-
237
- describe Surrounded::Context, 'skips affecting non-surrounded objects' do
238
- it 'works with non-surrounded objects' do
239
- context = BareObjectContext.new(123,'hello', User.new('Jim'))
240
- assert_equal '123 - hello - Jim', context.output
241
- end
242
- end
243
-
244
- class CollectionContext
245
- extend Surrounded::Context
246
-
247
- initialize :members, :others
248
-
249
- trigger :get_members_count do
250
- members.member_count
251
- end
252
-
253
- trigger :get_member_show do
254
- members.map(&:show).join(', ')
255
- end
256
-
257
- role :members do
258
- def member_count
259
- size
260
- end
261
- end
262
-
263
- role :member do
264
- def show
265
- "member show"
266
- end
267
- end
268
-
269
- role :others do; end
270
- role :other do; end
271
-
272
- end
273
-
274
- describe Surrounded::Context, 'auto-assigning roles for collections' do
275
- let(:member_one){ User.new('Jim') }
276
- let(:member_two){ User.new('Amy') }
277
- let(:members){ [member_one, member_two] }
278
-
279
- let(:other_one){ User.new('Guille') }
280
- let(:other_two){ User.new('Jason') }
281
- let(:others){ [other_one, other_two] }
282
-
283
- let(:context){ CollectionContext.new(members, others) }
284
-
285
- it 'assigns the collection role to collections' do
286
- assert_equal members.size, context.get_members_count
287
- end
288
-
289
- it 'assigns a defined role to each item in a role player collection' do
290
- assert_equal "member show, member show", context.get_member_show
291
- end
292
- end
293
-
294
- describe Surrounded::Context, 'reusing context object' do
295
- let(:user){ User.new("Jim") }
296
- let(:other_user){ User.new("Guille") }
297
- let(:context){ TestContext.new(user, other_user) }
298
-
299
- it 'allows rebinding new players' do
300
- expect(context.access_other_object).must_equal 'Guille'
301
- context.rebind(user: User.new('Amy'), other_user: User.new('Elizabeth'))
302
- expect(context.access_other_object).must_equal 'Elizabeth'
303
- end
304
-
305
- it 'clears internal storage when rebinding' do
306
- originals = context.instance_variables.map{|var| context.instance_variable_get(var) }
307
- context.rebind(user: User.new('Amy'), other_user: User.new('Elizabeth'))
308
- new_ivars = context.instance_variables.map{|var| context.instance_variable_get(var) }
309
- originals.zip(new_ivars).each do |original_ivar, new_ivar|
310
- expect(original_ivar).wont_equal new_ivar
311
- end
312
- end
313
- end
314
-
315
- begin
316
- class Keyworder
317
- extend Surrounded::Context
318
-
319
- keyword_initialize :this, :that do
320
- self.instance_variable_set(:@defined_by_initializer_block, 'yes')
321
- end
322
- end
323
-
324
- describe Surrounded::Context, 'keyword initializers' do
325
- it 'works with keyword arguments' do
326
- assert Keyworder.new(this: User.new('Jim'), that: User.new('Guille'))
327
- end
328
-
329
- it 'raises errors with missing keywords' do
330
- err = assert_raises(ArgumentError){
331
- Keyworder.new(this: User.new('Amy'))
332
- }
333
- assert_match(/missing keyword: that/, err.message)
334
- end
335
-
336
- it 'evaluates a given block' do
337
- assert_equal 'yes', Keyworder.new(this: User.new('Jim'), that: User.new('Guille')).instance_variable_get(:@defined_by_initializer_block)
338
- end
339
- end
340
- rescue SyntaxError
341
- STDOUT.puts "No support for keywords"
342
- end
198
+ end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: surrounded
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.9.8
4
+ version: 0.9.9
5
5
  platform: ruby
6
6
  authors:
7
7
  - "'Jim Gay'"
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-06-16 00:00:00.000000000 Z
11
+ date: 2015-06-18 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: triad
@@ -83,14 +83,19 @@ files:
83
83
  - lib/surrounded/shortcuts.rb
84
84
  - lib/surrounded/version.rb
85
85
  - surrounded.gemspec
86
+ - test/casting_role_player_test.rb
87
+ - test/collection_role_players_test.rb
86
88
  - test/context_access_test.rb
87
89
  - test/context_forwarding_test.rb
90
+ - test/context_reuse_test.rb
88
91
  - test/context_shortcuts_test.rb
89
92
  - test/east_oriented_triggers_test.rb
90
93
  - test/example_delegate_class_test.rb
91
94
  - test/example_proxy_test.rb
92
95
  - test/example_threaded_test.rb
93
96
  - test/example_wrapper_test.rb
97
+ - test/initialization_test.rb
98
+ - test/non_surrounded_role_player_test.rb
94
99
  - test/override_methods_test.rb
95
100
  - test/role_context_method_test.rb
96
101
  - test/surrounded_context_test.rb
@@ -121,14 +126,19 @@ signing_key:
121
126
  specification_version: 4
122
127
  summary: Create encapsulated environments for your objects.
123
128
  test_files:
129
+ - test/casting_role_player_test.rb
130
+ - test/collection_role_players_test.rb
124
131
  - test/context_access_test.rb
125
132
  - test/context_forwarding_test.rb
133
+ - test/context_reuse_test.rb
126
134
  - test/context_shortcuts_test.rb
127
135
  - test/east_oriented_triggers_test.rb
128
136
  - test/example_delegate_class_test.rb
129
137
  - test/example_proxy_test.rb
130
138
  - test/example_threaded_test.rb
131
139
  - test/example_wrapper_test.rb
140
+ - test/initialization_test.rb
141
+ - test/non_surrounded_role_player_test.rb
132
142
  - test/override_methods_test.rb
133
143
  - test/role_context_method_test.rb
134
144
  - test/surrounded_context_test.rb