surrounded 1.1.0 → 1.1.2
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/Changelog.md +14 -17
- data/LICENSE.txt +1 -1
- data/README.md +3 -3
- data/Rakefile +12 -5
- data/lib/surrounded/access_control.rb +12 -11
- data/lib/surrounded/context/forwarding.rb +10 -10
- data/lib/surrounded/context/initializing.rb +8 -6
- data/lib/surrounded/context/name_collision_detector.rb +17 -17
- data/lib/surrounded/context/negotiator.rb +7 -8
- data/lib/surrounded/context/role_builders.rb +9 -12
- data/lib/surrounded/context/role_map.rb +34 -12
- data/lib/surrounded/context/seclusion.rb +9 -3
- data/lib/surrounded/context/trigger_controls.rb +11 -13
- data/lib/surrounded/context.rb +66 -60
- data/lib/surrounded/east_oriented.rb +4 -4
- data/lib/surrounded/exceptions.rb +1 -1
- data/lib/surrounded/shortcuts.rb +6 -8
- data/lib/surrounded/version.rb +1 -1
- data/lib/surrounded.rb +7 -7
- data/surrounded.gemspec +21 -15
- data/test/{casting_role_player_test.rb → casting_test_helper.rb} +4 -3
- data/test/collection_role_players_test.rb +16 -16
- data/test/context_access_test.rb +31 -30
- data/test/context_forwarding_test.rb +30 -30
- data/test/context_reuse_test.rb +14 -14
- data/test/context_shortcuts_test.rb +18 -16
- data/test/east_oriented_triggers_test.rb +14 -13
- data/test/example_delegate_class_test.rb +8 -8
- data/test/example_proxy_test.rb +25 -23
- data/test/example_threaded_test.rb +13 -13
- data/test/example_wrapper_test.rb +7 -7
- data/test/initialization_test.rb +24 -25
- data/test/name_collisions_test.rb +48 -42
- data/test/non_surrounded_role_player_test.rb +8 -8
- data/test/override_methods_test.rb +9 -9
- data/test/role_context_method_test.rb +129 -119
- data/test/role_identity_test.rb +39 -0
- data/test/surrounded_context_test.rb +71 -62
- data/test/surrounded_test.rb +13 -15
- data/test/test_helper.rb +5 -4
- data/test/threaded_context_test.rb +70 -0
- metadata +9 -38
- data/.codeclimate.yml +0 -4
- data/.github/workflows/codeql-analysis.yml +0 -70
- data/.github/workflows/test.yml +0 -18
- data/.gitignore +0 -19
- data/.pullreview.yml +0 -4
- data/.simplecov +0 -3
- data/Gemfile +0 -9
- data/examples/bottles.rb +0 -135
- data/examples/rails.rb +0 -57
data/lib/surrounded/context.rb
CHANGED
|
@@ -1,15 +1,14 @@
|
|
|
1
|
-
require
|
|
2
|
-
require
|
|
3
|
-
require
|
|
4
|
-
require
|
|
5
|
-
require
|
|
6
|
-
require
|
|
7
|
-
require
|
|
8
|
-
require
|
|
9
|
-
require
|
|
10
|
-
require
|
|
11
|
-
require
|
|
12
|
-
require 'surrounded/context/name_collision_detector'
|
|
1
|
+
require "surrounded/exceptions"
|
|
2
|
+
require "surrounded/context/role_map"
|
|
3
|
+
require "surrounded/context/seclusion"
|
|
4
|
+
require "surrounded/context/role_builders"
|
|
5
|
+
require "surrounded/context/initializing"
|
|
6
|
+
require "surrounded/context/forwarding"
|
|
7
|
+
require "surrounded/context/trigger_controls"
|
|
8
|
+
require "surrounded/access_control"
|
|
9
|
+
require "surrounded/shortcuts"
|
|
10
|
+
require "surrounded/east_oriented"
|
|
11
|
+
require "surrounded/context/name_collision_detector"
|
|
13
12
|
|
|
14
13
|
# Extend your classes with Surrounded::Context to handle their
|
|
15
14
|
# initialization and application of behaviors to the role players
|
|
@@ -27,16 +26,13 @@ module Surrounded
|
|
|
27
26
|
include InstanceMethods
|
|
28
27
|
|
|
29
28
|
trigger_mod = Module.new
|
|
30
|
-
const_set(
|
|
29
|
+
const_set(:TriggerMethods, trigger_mod)
|
|
31
30
|
include trigger_mod
|
|
32
31
|
|
|
33
32
|
extend TriggerControls
|
|
34
|
-
|
|
35
33
|
}
|
|
36
34
|
end
|
|
37
35
|
|
|
38
|
-
private
|
|
39
|
-
|
|
40
36
|
# Set the default type of implementation for role methods for all contexts.
|
|
41
37
|
def self.default_role_type
|
|
42
38
|
@default_role_type ||= :module
|
|
@@ -46,6 +42,8 @@ module Surrounded
|
|
|
46
42
|
attr_writer :default_role_type
|
|
47
43
|
end
|
|
48
44
|
|
|
45
|
+
private
|
|
46
|
+
|
|
49
47
|
def default_role_type
|
|
50
48
|
@default_role_type ||= Surrounded::Context.default_role_type
|
|
51
49
|
end
|
|
@@ -56,13 +54,19 @@ module Surrounded
|
|
|
56
54
|
end
|
|
57
55
|
|
|
58
56
|
# Provide the ability to create access control methods for your triggers.
|
|
59
|
-
def protect_triggers
|
|
57
|
+
def protect_triggers
|
|
58
|
+
extend(::Surrounded::AccessControl)
|
|
59
|
+
end
|
|
60
60
|
|
|
61
61
|
# Automatically create class methods for each trigger method.
|
|
62
|
-
def shortcut_triggers
|
|
62
|
+
def shortcut_triggers
|
|
63
|
+
extend(::Surrounded::Shortcuts)
|
|
64
|
+
end
|
|
63
65
|
|
|
64
66
|
# Automatically return the context object from trigger methods.
|
|
65
|
-
def east_oriented_triggers
|
|
67
|
+
def east_oriented_triggers
|
|
68
|
+
extend(::Surrounded::EastOriented)
|
|
69
|
+
end
|
|
66
70
|
|
|
67
71
|
# === Utility shortcuts
|
|
68
72
|
|
|
@@ -91,8 +95,8 @@ module Surrounded
|
|
|
91
95
|
# is allowed to inquire about the roles.
|
|
92
96
|
def role?(name, &block)
|
|
93
97
|
return false unless role_map.role?(name)
|
|
94
|
-
accessor = block.binding.eval(
|
|
95
|
-
role_map.role_player?(accessor) && role_map.
|
|
98
|
+
accessor = block.binding.eval("self")
|
|
99
|
+
role_map.role_player?(accessor) && role_map.current_player(name)
|
|
96
100
|
end
|
|
97
101
|
|
|
98
102
|
# Check if a given object is a role player in the context.
|
|
@@ -119,7 +123,7 @@ module Surrounded
|
|
|
119
123
|
private
|
|
120
124
|
|
|
121
125
|
def clear_instance_variables
|
|
122
|
-
instance_variables.each{|ivar| remove_instance_variable(ivar) }
|
|
126
|
+
instance_variables.each { |ivar| remove_instance_variable(ivar) }
|
|
123
127
|
end
|
|
124
128
|
|
|
125
129
|
def role_map
|
|
@@ -129,8 +133,8 @@ module Surrounded
|
|
|
129
133
|
def map_roles(role_object_array)
|
|
130
134
|
detect_collisions role_object_array
|
|
131
135
|
role_object_array.to_a.each do |role, object|
|
|
132
|
-
if
|
|
133
|
-
|
|
136
|
+
if respond_to?("map_role_#{role}")
|
|
137
|
+
send("map_role_#{role}", object)
|
|
134
138
|
else
|
|
135
139
|
map_role(role, role_behavior_name(role), object)
|
|
136
140
|
map_role_collection(role, role_behavior_name(role), object)
|
|
@@ -149,28 +153,26 @@ module Surrounded
|
|
|
149
153
|
end
|
|
150
154
|
|
|
151
155
|
def map_role(role, mod_name, object)
|
|
152
|
-
instance_variable_set("@#{role}", object)
|
|
153
156
|
role_map.update(role, role_module_basename(mod_name), object)
|
|
154
157
|
end
|
|
155
158
|
|
|
156
159
|
def apply_behavior(role, behavior, object)
|
|
157
160
|
if behavior && role_const_defined?(behavior)
|
|
158
|
-
applicator = if
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
161
|
+
applicator = if respond_to?("apply_behavior_#{role}")
|
|
162
|
+
method("apply_behavior_#{role}")
|
|
163
|
+
elsif role_const(behavior).is_a?(Class)
|
|
164
|
+
method(:apply_class_behavior)
|
|
165
|
+
else
|
|
166
|
+
method(:apply_module_behavior)
|
|
167
|
+
end
|
|
165
168
|
|
|
166
169
|
role_player = applicator.call(role_const(behavior), object)
|
|
167
|
-
map_role(role, behavior, role_player)
|
|
168
170
|
end
|
|
169
171
|
role_player || object
|
|
170
172
|
end
|
|
171
173
|
|
|
172
174
|
def apply_module_behavior(mod, obj)
|
|
173
|
-
adder_name = module_extension_methods.find{|meth| obj.respond_to?(meth) }
|
|
175
|
+
adder_name = module_extension_methods.find { |meth| obj.respond_to?(meth) }
|
|
174
176
|
return obj unless adder_name
|
|
175
177
|
|
|
176
178
|
obj.method(adder_name).call(mod)
|
|
@@ -178,7 +180,7 @@ module Surrounded
|
|
|
178
180
|
end
|
|
179
181
|
|
|
180
182
|
def apply_class_behavior(klass, obj)
|
|
181
|
-
wrapper_name = wrap_methods.find{|meth| klass.respond_to?(meth) }
|
|
183
|
+
wrapper_name = wrap_methods.find { |meth| klass.respond_to?(meth) }
|
|
182
184
|
return obj if !wrapper_name
|
|
183
185
|
klass.method(wrapper_name).call(obj)
|
|
184
186
|
end
|
|
@@ -190,11 +192,11 @@ module Surrounded
|
|
|
190
192
|
end
|
|
191
193
|
end
|
|
192
194
|
|
|
193
|
-
role_player = if
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
195
|
+
role_player = if respond_to?("remove_behavior_#{role}")
|
|
196
|
+
send("remove_behavior_#{role}", role_const(behavior), object)
|
|
197
|
+
elsif remover_name
|
|
198
|
+
object.send(remover_name)
|
|
199
|
+
end
|
|
198
200
|
|
|
199
201
|
role_player || object
|
|
200
202
|
end
|
|
@@ -202,19 +204,22 @@ module Surrounded
|
|
|
202
204
|
def apply_behaviors
|
|
203
205
|
role_map.each do |role, mod_name, object|
|
|
204
206
|
player = apply_behavior(role, mod_name, object)
|
|
207
|
+
role_map.apply(role, player)
|
|
205
208
|
if player.respond_to?(:store_context, true)
|
|
206
|
-
player.__send__(:store_context)
|
|
209
|
+
player.__send__(:store_context) {}
|
|
207
210
|
end
|
|
208
211
|
end
|
|
209
212
|
end
|
|
210
213
|
|
|
211
214
|
def remove_behaviors
|
|
212
|
-
role_map.each do |role, mod_name,
|
|
215
|
+
role_map.each do |role, mod_name, object|
|
|
216
|
+
player = role_map.current_player(role)
|
|
213
217
|
if player.respond_to?(:remove_context, true)
|
|
214
|
-
player.__send__(:remove_context)
|
|
218
|
+
player.__send__(:remove_context) {}
|
|
215
219
|
end
|
|
216
220
|
remove_behavior(role, mod_name, player)
|
|
217
221
|
end
|
|
222
|
+
role_map.reset_applied
|
|
218
223
|
end
|
|
219
224
|
|
|
220
225
|
# List of possible methods to use to add behavior to an object from a module.
|
|
@@ -242,7 +247,7 @@ module Surrounded
|
|
|
242
247
|
end
|
|
243
248
|
|
|
244
249
|
def role_module_basename(mod)
|
|
245
|
-
mod.to_s.split(
|
|
250
|
+
mod.to_s.split("::").last
|
|
246
251
|
end
|
|
247
252
|
|
|
248
253
|
def role_const(name)
|
|
@@ -262,33 +267,34 @@ module Surrounded
|
|
|
262
267
|
name.singularize
|
|
263
268
|
else
|
|
264
269
|
# good enough for now but should be updated with better rules
|
|
265
|
-
name.to_s.
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
270
|
+
string = name.to_s.dup
|
|
271
|
+
if string.end_with?("ies")
|
|
272
|
+
string.sub(/ies\z/, "y")
|
|
273
|
+
elsif string.end_with?("s")
|
|
274
|
+
string.sub(/s\z/, "")
|
|
275
|
+
else
|
|
276
|
+
string
|
|
271
277
|
end
|
|
272
278
|
end
|
|
273
279
|
end
|
|
274
280
|
end
|
|
275
281
|
|
|
276
282
|
class RoleName
|
|
277
|
-
def initialize(string, suffix=nil)
|
|
278
|
-
@string = string
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
283
|
+
def initialize(string, suffix = nil)
|
|
284
|
+
@string = string
|
|
285
|
+
.to_s
|
|
286
|
+
.split("_")
|
|
287
|
+
.map { |part|
|
|
288
|
+
part.capitalize
|
|
289
|
+
}
|
|
290
|
+
.join
|
|
291
|
+
.sub(/_\d+/, "") + suffix.to_s
|
|
286
292
|
end
|
|
287
293
|
|
|
288
294
|
def to_str
|
|
289
295
|
@string
|
|
290
296
|
end
|
|
291
|
-
|
|
297
|
+
alias_method :to_s, :to_str
|
|
292
298
|
|
|
293
299
|
def to_sym
|
|
294
300
|
@string.to_sym
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
module Surrounded
|
|
2
2
|
module Exceptions
|
|
3
3
|
def self.define(klass, exceptions:, namespace: Surrounded::Context)
|
|
4
|
-
Array(exceptions).each{ |exception|
|
|
4
|
+
Array(exceptions).each { |exception|
|
|
5
5
|
unless klass.const_defined?(exception)
|
|
6
6
|
klass.const_set(exception, Class.new(namespace.const_get(exception)))
|
|
7
7
|
end
|
data/lib/surrounded/shortcuts.rb
CHANGED
|
@@ -1,21 +1,19 @@
|
|
|
1
1
|
module Surrounded
|
|
2
2
|
module Shortcuts
|
|
3
3
|
private
|
|
4
|
-
|
|
4
|
+
|
|
5
5
|
def define_shortcut(name)
|
|
6
6
|
# if keyword initialize
|
|
7
|
-
if instance_method(:initialize).parameters.dig(0,0) == :keyreq
|
|
7
|
+
if instance_method(:initialize).parameters.dig(0, 0) == :keyreq
|
|
8
8
|
singleton_class.send(:define_method, name) do |**args|
|
|
9
|
-
instance =
|
|
10
|
-
|
|
11
|
-
end
|
|
9
|
+
instance = new(**args)
|
|
10
|
+
|
|
12
11
|
instance.public_send(name)
|
|
13
12
|
end
|
|
14
13
|
else # non-keyword initialize
|
|
15
14
|
singleton_class.send(:define_method, name) do |*args|
|
|
16
|
-
instance =
|
|
17
|
-
|
|
18
|
-
end
|
|
15
|
+
instance = new(*args)
|
|
16
|
+
|
|
19
17
|
instance.public_send(name)
|
|
20
18
|
end
|
|
21
19
|
end
|
data/lib/surrounded/version.rb
CHANGED
data/lib/surrounded.rb
CHANGED
|
@@ -3,23 +3,22 @@ require "surrounded/context"
|
|
|
3
3
|
require "singleton"
|
|
4
4
|
|
|
5
5
|
# This module should be added to objects which will enter
|
|
6
|
-
# into context objects.
|
|
6
|
+
# into context objects.
|
|
7
7
|
#
|
|
8
8
|
# Its main purpose is to keep a reference to the context
|
|
9
9
|
# and to implement method_missing to handle the relationship
|
|
10
10
|
# to other objects in the context.
|
|
11
11
|
module Surrounded
|
|
12
|
-
|
|
13
12
|
private
|
|
14
13
|
|
|
15
14
|
def store_context(&block)
|
|
16
|
-
accessor = block.binding.eval(
|
|
15
|
+
accessor = block.binding.eval("self")
|
|
17
16
|
surroundings.unshift(accessor)
|
|
18
17
|
self
|
|
19
18
|
end
|
|
20
19
|
|
|
21
20
|
def remove_context(&block)
|
|
22
|
-
accessor = block.binding.eval(
|
|
21
|
+
accessor = block.binding.eval("self")
|
|
23
22
|
surroundings.shift if surroundings.include?(accessor)
|
|
24
23
|
self
|
|
25
24
|
end
|
|
@@ -33,15 +32,16 @@ module Surrounded
|
|
|
33
32
|
end
|
|
34
33
|
|
|
35
34
|
def method_missing(meth, *args, &block)
|
|
36
|
-
context.role?(meth){} || super
|
|
35
|
+
context.role?(meth) {} || super
|
|
37
36
|
end
|
|
38
37
|
|
|
39
|
-
def respond_to_missing?(meth, include_private=false)
|
|
40
|
-
!!context.role?(meth){} || super
|
|
38
|
+
def respond_to_missing?(meth, include_private = false)
|
|
39
|
+
!!context.role?(meth) {} || super
|
|
41
40
|
end
|
|
42
41
|
|
|
43
42
|
class NullContext
|
|
44
43
|
include Singleton
|
|
44
|
+
|
|
45
45
|
def role?(*args)
|
|
46
46
|
nil
|
|
47
47
|
end
|
data/surrounded.gemspec
CHANGED
|
@@ -1,24 +1,30 @@
|
|
|
1
|
-
|
|
2
|
-
lib = File.expand_path('../lib', __FILE__)
|
|
1
|
+
lib = File.expand_path("../lib", __FILE__)
|
|
3
2
|
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
|
4
|
-
require
|
|
3
|
+
require "surrounded/version"
|
|
5
4
|
|
|
6
5
|
Gem::Specification.new do |spec|
|
|
7
|
-
spec.name
|
|
8
|
-
spec.version
|
|
9
|
-
spec.authors
|
|
10
|
-
spec.email
|
|
11
|
-
spec.description
|
|
12
|
-
spec.summary
|
|
13
|
-
spec.homepage
|
|
14
|
-
spec.license
|
|
6
|
+
spec.name = "surrounded"
|
|
7
|
+
spec.version = Surrounded.version
|
|
8
|
+
spec.authors = ["'Jim Gay'"]
|
|
9
|
+
spec.email = ["jim@saturnflyer.com"]
|
|
10
|
+
spec.description = "Gives an object implicit access to other objects in it's environment."
|
|
11
|
+
spec.summary = "Create encapsulated environments for your objects."
|
|
12
|
+
spec.homepage = "http://github.com/saturnflyer/surrounded"
|
|
13
|
+
spec.license = "MIT"
|
|
15
14
|
|
|
16
|
-
spec.files
|
|
17
|
-
|
|
18
|
-
|
|
15
|
+
spec.files = Dir[
|
|
16
|
+
"lib/**/*",
|
|
17
|
+
"Rakefile",
|
|
18
|
+
"README.md",
|
|
19
|
+
"Changelog.md",
|
|
20
|
+
"LICENSE.txt",
|
|
21
|
+
"test/**/*",
|
|
22
|
+
"surrounded.gemspec"
|
|
23
|
+
]
|
|
24
|
+
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
|
19
25
|
spec.require_paths = ["lib"]
|
|
20
26
|
|
|
21
|
-
spec.add_dependency "triad",
|
|
27
|
+
spec.add_dependency "triad", ">= 0.3.0"
|
|
22
28
|
|
|
23
29
|
spec.add_development_dependency "rake"
|
|
24
30
|
end
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
require
|
|
1
|
+
require "test_helper"
|
|
2
|
+
require "casting_test_helper"
|
|
2
3
|
|
|
3
4
|
class CollectionContext
|
|
4
5
|
extend Surrounded::Context
|
|
@@ -10,7 +11,7 @@ class CollectionContext
|
|
|
10
11
|
end
|
|
11
12
|
|
|
12
13
|
trigger :get_member_show do
|
|
13
|
-
members.map(&:show).join(
|
|
14
|
+
members.map(&:show).join(", ")
|
|
14
15
|
end
|
|
15
16
|
|
|
16
17
|
role :members do
|
|
@@ -25,27 +26,26 @@ class CollectionContext
|
|
|
25
26
|
end
|
|
26
27
|
end
|
|
27
28
|
|
|
28
|
-
role :others
|
|
29
|
-
role :other
|
|
30
|
-
|
|
29
|
+
role :others, &proc {}
|
|
30
|
+
role :other, &proc {}
|
|
31
31
|
end
|
|
32
32
|
|
|
33
|
-
describe Surrounded::Context,
|
|
34
|
-
let(:member_one){ User.new(
|
|
35
|
-
let(:member_two){ User.new(
|
|
36
|
-
let(:members){ [member_one, member_two] }
|
|
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
37
|
|
|
38
|
-
let(:other_one){ User.new(
|
|
39
|
-
let(:other_two){ User.new(
|
|
40
|
-
let(:others){ [other_one, other_two] }
|
|
38
|
+
let(:other_one) { User.new("Guille") }
|
|
39
|
+
let(:other_two) { User.new("Jason") }
|
|
40
|
+
let(:others) { [other_one, other_two] }
|
|
41
41
|
|
|
42
|
-
let(:context){ CollectionContext.new(members: members, others: others) }
|
|
42
|
+
let(:context) { CollectionContext.new(members: members, others: others) }
|
|
43
43
|
|
|
44
|
-
it
|
|
44
|
+
it "assigns the collection role to collections" do
|
|
45
45
|
assert_equal members.size, context.get_members_count
|
|
46
46
|
end
|
|
47
47
|
|
|
48
|
-
it
|
|
48
|
+
it "assigns a defined role to each item in a role player collection" do
|
|
49
49
|
assert_equal "member show, member show", context.get_member_show
|
|
50
50
|
end
|
|
51
|
-
end
|
|
51
|
+
end
|
data/test/context_access_test.rb
CHANGED
|
@@ -1,62 +1,63 @@
|
|
|
1
|
-
require
|
|
2
|
-
require
|
|
1
|
+
require "test_helper"
|
|
2
|
+
require "minitest/mock"
|
|
3
3
|
|
|
4
4
|
class FilteredContext
|
|
5
5
|
extend Surrounded::Context
|
|
6
|
+
|
|
6
7
|
protect_triggers
|
|
7
|
-
|
|
8
|
+
|
|
8
9
|
initialize :user, :other_user
|
|
9
|
-
|
|
10
|
+
|
|
10
11
|
trigger :if_ready do
|
|
11
|
-
|
|
12
|
+
"ready"
|
|
12
13
|
end
|
|
13
|
-
|
|
14
|
+
|
|
14
15
|
guard :if_ready do
|
|
15
|
-
user.name !=
|
|
16
|
+
user.name != "Amy"
|
|
16
17
|
end
|
|
17
|
-
|
|
18
|
+
|
|
18
19
|
trigger :check_disallow_behavior do
|
|
19
20
|
# used for disallow check
|
|
20
21
|
end
|
|
21
|
-
|
|
22
|
+
|
|
22
23
|
disallow :check_disallow_behavior do
|
|
23
24
|
user.special
|
|
24
25
|
end
|
|
25
|
-
|
|
26
|
+
|
|
26
27
|
trigger :unguarded do
|
|
27
28
|
# used for disallow check
|
|
28
29
|
end
|
|
29
30
|
|
|
30
31
|
role :user do
|
|
31
32
|
def special
|
|
32
|
-
|
|
33
|
+
"special user method"
|
|
33
34
|
end
|
|
34
35
|
end
|
|
35
36
|
end
|
|
36
37
|
|
|
37
|
-
describe Surrounded::Context,
|
|
38
|
-
let(:user){ User.new("Jim") }
|
|
39
|
-
let(:other_user){ User.new("Guille") }
|
|
40
|
-
let(:context){ FilteredContext.new(user: user, other_user: other_user) }
|
|
41
|
-
|
|
42
|
-
it
|
|
38
|
+
describe Surrounded::Context, "access control" do
|
|
39
|
+
let(:user) { User.new("Jim") }
|
|
40
|
+
let(:other_user) { User.new("Guille") }
|
|
41
|
+
let(:context) { FilteredContext.new(user: user, other_user: other_user) }
|
|
42
|
+
|
|
43
|
+
it "includes triggers when allowed" do
|
|
43
44
|
context.stub(:disallow_if_ready?, false) do
|
|
44
45
|
assert context.triggers.include?(:if_ready)
|
|
45
46
|
end
|
|
46
47
|
end
|
|
47
48
|
|
|
48
|
-
it
|
|
49
|
+
it "excludes triggers when not allowed" do
|
|
49
50
|
refute context.triggers.include?(:if_ready)
|
|
50
51
|
end
|
|
51
|
-
|
|
52
|
-
it
|
|
53
|
-
error = assert_raises(::FilteredContext::AccessError){
|
|
52
|
+
|
|
53
|
+
it "raises error specific to the context class when trigger method not allowed" do
|
|
54
|
+
error = assert_raises(::FilteredContext::AccessError) {
|
|
54
55
|
context.if_ready
|
|
55
56
|
}
|
|
56
57
|
assert_match(/access to FilteredContext#if_ready is not allowed/i, error.message)
|
|
57
58
|
end
|
|
58
|
-
|
|
59
|
-
it
|
|
59
|
+
|
|
60
|
+
it "supports rescuing from Surrounded defined error when trigger method not allowed" do
|
|
60
61
|
begin
|
|
61
62
|
context.if_ready
|
|
62
63
|
rescue ::Surrounded::Context::AccessError => error
|
|
@@ -64,20 +65,20 @@ describe Surrounded::Context, 'access control' do
|
|
|
64
65
|
end
|
|
65
66
|
assert_match(/access to FilteredContext#if_ready is not allowed/i, error.message)
|
|
66
67
|
end
|
|
67
|
-
|
|
68
|
-
it
|
|
69
|
-
assert_equal
|
|
68
|
+
|
|
69
|
+
it "applies roles in disallow blocks" do
|
|
70
|
+
assert_equal "special user method", context.disallow_check_disallow_behavior?
|
|
70
71
|
end
|
|
71
72
|
|
|
72
|
-
it
|
|
73
|
+
it "lets you ask if the object will allow a method" do
|
|
73
74
|
assert context.allow?(:unguarded)
|
|
74
75
|
refute context.allow?(:check_disallow_behavior)
|
|
75
76
|
end
|
|
76
77
|
|
|
77
|
-
it
|
|
78
|
-
error = assert_raises(NoMethodError){
|
|
78
|
+
it "complains if you ask about an undefined method" do
|
|
79
|
+
error = assert_raises(NoMethodError) {
|
|
79
80
|
context.allow?(:not_a_defined_method)
|
|
80
81
|
}
|
|
81
82
|
assert_match(/undefined method `not_a_defined_method' for #<#{context.class}/, error.message)
|
|
82
83
|
end
|
|
83
|
-
end
|
|
84
|
+
end
|