surrounded 1.1.0 → 1.1.1

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.
Files changed (50) hide show
  1. checksums.yaml +4 -4
  2. data/Changelog.md +11 -20
  3. data/LICENSE.txt +1 -1
  4. data/README.md +3 -3
  5. data/Rakefile +12 -5
  6. data/lib/surrounded/access_control.rb +12 -11
  7. data/lib/surrounded/context/forwarding.rb +10 -10
  8. data/lib/surrounded/context/initializing.rb +8 -6
  9. data/lib/surrounded/context/name_collision_detector.rb +17 -17
  10. data/lib/surrounded/context/negotiator.rb +7 -8
  11. data/lib/surrounded/context/role_builders.rb +7 -7
  12. data/lib/surrounded/context/role_map.rb +6 -8
  13. data/lib/surrounded/context/trigger_controls.rb +11 -13
  14. data/lib/surrounded/context.rb +61 -56
  15. data/lib/surrounded/east_oriented.rb +4 -4
  16. data/lib/surrounded/exceptions.rb +1 -1
  17. data/lib/surrounded/shortcuts.rb +6 -8
  18. data/lib/surrounded/version.rb +1 -1
  19. data/lib/surrounded.rb +7 -7
  20. data/surrounded.gemspec +21 -15
  21. data/test/{casting_role_player_test.rb → casting_test_helper.rb} +4 -3
  22. data/test/collection_role_players_test.rb +16 -16
  23. data/test/context_access_test.rb +31 -30
  24. data/test/context_forwarding_test.rb +30 -30
  25. data/test/context_reuse_test.rb +14 -14
  26. data/test/context_shortcuts_test.rb +18 -16
  27. data/test/east_oriented_triggers_test.rb +14 -13
  28. data/test/example_delegate_class_test.rb +8 -8
  29. data/test/example_proxy_test.rb +25 -23
  30. data/test/example_threaded_test.rb +13 -13
  31. data/test/example_wrapper_test.rb +7 -7
  32. data/test/initialization_test.rb +24 -25
  33. data/test/name_collisions_test.rb +48 -42
  34. data/test/non_surrounded_role_player_test.rb +8 -8
  35. data/test/override_methods_test.rb +9 -9
  36. data/test/role_context_method_test.rb +129 -119
  37. data/test/surrounded_context_test.rb +71 -62
  38. data/test/surrounded_test.rb +13 -15
  39. data/test/test_helper.rb +5 -4
  40. data/test/threaded_context_test.rb +70 -0
  41. metadata +8 -38
  42. data/.codeclimate.yml +0 -4
  43. data/.github/workflows/codeql-analysis.yml +0 -70
  44. data/.github/workflows/test.yml +0 -18
  45. data/.gitignore +0 -19
  46. data/.pullreview.yml +0 -4
  47. data/.simplecov +0 -3
  48. data/Gemfile +0 -9
  49. data/examples/bottles.rb +0 -135
  50. data/examples/rails.rb +0 -57
@@ -1,4 +1,4 @@
1
- require 'test_helper'
1
+ require "test_helper"
2
2
  ##
3
3
  # The problem is as follows: When an object already contains a method
4
4
  # that has the same name as an actor in the context, then the object
@@ -13,19 +13,22 @@ require 'test_helper'
13
13
  class HasNameCollision
14
14
  include Surrounded
15
15
 
16
- attr_accessor :will_collide # should always return nil
16
+ attr_reader :will_collide # should always return nil
17
17
 
18
18
  def assert_has_role
19
19
  true
20
20
  end
21
21
 
22
- def will_collide=(_); end
22
+ def will_collide=(_)
23
+ @will_collide = nil
24
+ end
23
25
  end
24
26
 
25
27
  class ShouldCollide
26
28
  include Surrounded
29
+
27
30
  def collide
28
- return 'Method called in ShouldCollide'
31
+ "Method called in ShouldCollide"
29
32
  end
30
33
  end
31
34
 
@@ -66,111 +69,114 @@ class ContextWithMultipleCollisions
66
69
  end
67
70
 
68
71
  class First
72
+ def second
73
+ end
69
74
 
70
- def second;end
71
- def third;end
75
+ def third
76
+ end
72
77
  end
73
78
 
74
79
  class Second
75
- def first;end
80
+ def first
81
+ end
76
82
 
77
- def third;end
83
+ def third
84
+ end
78
85
  end
79
86
 
80
87
  class Third
81
- def first;end
82
- def second;end
88
+ def first
89
+ end
83
90
 
91
+ def second
92
+ end
84
93
  end
85
94
 
86
- describe 'handling name collisions' do
87
-
88
- let(:new_context_with_collision){
95
+ describe "handling name collisions" do
96
+ let(:new_context_with_collision) {
89
97
  ContextOverridesName.new(base: HasNameCollision.new, will_collide: ShouldCollide.new)
90
98
  }
91
99
 
92
100
  after do
93
- ContextOverridesName.instance_eval{
101
+ ContextOverridesName.instance_eval {
94
102
  remove_instance_variable :@handler if defined?(@handler)
95
103
  }
96
104
  end
97
105
 
98
106
  def set_handler(handler)
99
- ContextOverridesName.instance_eval{
107
+ ContextOverridesName.instance_eval {
100
108
  on_name_collision handler
101
109
  }
102
110
  end
103
111
 
104
- it 'is works properly without handling collisions' do
112
+ it "is works properly without handling collisions" do
105
113
  assert new_context_with_collision.check_setup
106
114
  end
107
115
 
108
- it 'allows a name collision' do
109
- err = assert_raises(NoMethodError){
116
+ it "allows a name collision" do
117
+ err = assert_raises(NoMethodError) {
110
118
  new_context_with_collision.induce_collision
111
119
  }
112
- assert_match(/undefined method \`collide' for nil:NilClass/, err.message)
120
+ assert_match(/undefined method [`']collide['`] for nil/, err.message)
113
121
  end
114
122
 
115
- it 'can raise an exception' do
123
+ it "can raise an exception" do
116
124
  set_handler :raise
117
- assert_raises(ContextOverridesName::NameCollisionError){
125
+ assert_raises(ContextOverridesName::NameCollisionError) {
118
126
  new_context_with_collision
119
127
  }
120
128
  end
121
129
 
122
- it 'can print a warning' do
130
+ it "can print a warning" do
123
131
  set_handler :warn
124
132
  assert_output(nil, "base has name collisions with [:will_collide]\n") {
125
133
  new_context_with_collision
126
134
  }
127
135
  end
128
136
 
129
- it 'can ignore collisions' do
137
+ it "can ignore collisions" do
130
138
  set_handler :nothing
131
139
  assert_output(nil, nil) {
132
140
  new_context_with_collision
133
141
  }
134
142
  end
135
143
 
136
- it 'raises an error with an unknown handler' do
144
+ it "raises an error with an unknown handler" do
137
145
  set_handler :barf
138
146
  err = assert_raises(ArgumentError) {
139
147
  new_context_with_collision
140
148
  }
141
- expect(err.message).must_match(/your name collision handler was set to \`barf' but there is no instance nor class method of that name/)
149
+ expect(err.message).must_match(/your name collision handler was set to `barf' but there is no instance nor class method of that name/)
142
150
  end
143
151
 
144
- let(:create_context_with_multiple_collisions){
152
+ let(:create_context_with_multiple_collisions) {
145
153
  ContextWithMultipleCollisions.new(first: First.new, second: Second.new, third: Third.new)
146
154
  }
147
155
 
148
- it 'can handle multiple collisions' do
149
- expected_message = <<ERR
150
- first has name collisions with [:second, :third]
151
- second has name collisions with [:first, :third]
152
- third has name collisions with [:first, :second]
153
- ERR
154
- assert_output(nil, expected_message){
156
+ it "can handle multiple collisions" do
157
+ expected_message = <<~ERR
158
+ first has name collisions with [:second, :third]
159
+ second has name collisions with [:first, :third]
160
+ third has name collisions with [:first, :second]
161
+ ERR
162
+ assert_output(nil, expected_message) {
155
163
  create_context_with_multiple_collisions
156
164
  }
157
165
  end
158
166
 
159
- it 'can use a class method' do
160
- class ContextOverridesName
161
- def self.class_method_handler(message)
162
- puts message
163
- end
167
+ it "can use a class method" do
168
+ ContextOverridesName.define_singleton_method(:class_method_handler) do |message|
169
+ puts message
164
170
  end
165
171
  set_handler :class_method_handler
166
- assert_output("base has name collisions with [:will_collide]\n"){
172
+ assert_output("base has name collisions with [:will_collide]\n") {
167
173
  new_context_with_collision
168
174
  }
169
175
  end
170
176
 
171
- it 'can use a proc' do
172
- set_handler ->(message){ puts "message from a proc: #{message}"}
173
- assert_output("message from a proc: base has name collisions with [:will_collide]\n"){
177
+ it "can use a proc" do
178
+ set_handler ->(message) { puts "message from a proc: #{message}" }
179
+ assert_output("message from a proc: base has name collisions with [:will_collide]\n") {
174
180
  new_context_with_collision
175
181
  }
176
182
  end
@@ -1,16 +1,16 @@
1
- require 'test_helper'
1
+ require "test_helper"
2
2
 
3
3
  class BareObjectContext
4
4
  extend Surrounded::Context
5
5
 
6
6
  def initialize(number, string, user)
7
- map_roles(:number => number, :string => string, :user => user)
7
+ map_roles(number: number, string: string, user: user)
8
8
  end
9
9
  private_attr_reader :number, :string, :user
10
10
 
11
11
  role :user do
12
12
  def output
13
- [number.to_s, string, name].join(' - ')
13
+ [number.to_s, string, name].join(" - ")
14
14
  end
15
15
  end
16
16
 
@@ -19,9 +19,9 @@ class BareObjectContext
19
19
  end
20
20
  end
21
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
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
26
  end
27
- end
27
+ end
@@ -1,4 +1,4 @@
1
- require 'test_helper'
1
+ require "test_helper"
2
2
 
3
3
  class PrependedRoles
4
4
  extend Surrounded::Context
@@ -45,18 +45,18 @@ class PrependedRoles
45
45
  end
46
46
  end
47
47
 
48
- describe Surrounded::Context, 'custom role application' do
49
- let(:user){ User.new('Jim') }
50
- let(:other){ User.new('Amy') }
48
+ describe Surrounded::Context, "custom role application" do
49
+ let(:user) { User.new("Jim") }
50
+ let(:other) { User.new("Amy") }
51
51
 
52
- let(:context){ PrependedRoles.new(user: user, other: other) }
52
+ let(:context) { PrependedRoles.new(user: user, other: other) }
53
53
 
54
- it 'allows you to override existing methods on a role player' do
54
+ it "allows you to override existing methods on a role player" do
55
55
  assert_equal "Not what you thought, Jim", context.get_name
56
56
  assert_equal "Jim", user.name
57
57
  end
58
58
 
59
- it 'allows you to override the way a role is mapped' do
60
- assert_equal 'OtherStuff Amy', context.other_title
59
+ it "allows you to override the way a role is mapped" do
60
+ assert_equal "OtherStuff Amy", context.other_title
61
61
  end
62
- end
62
+ end
@@ -1,135 +1,142 @@
1
- require 'test_helper'
1
+ require "test_helper"
2
2
 
3
- describe Surrounded::Context, '.role' do
4
- class RoleContextTester
5
- extend Surrounded::Context
6
-
7
- role_methods :admin do
8
- end
3
+ class RoleContextTester
4
+ extend Surrounded::Context
5
+
6
+ role_methods :admin do
9
7
  end
10
-
11
- describe 'modules' do
12
- it 'creates a module' do
8
+ end
9
+
10
+ describe Surrounded::Context, ".role" do
11
+ describe "modules" do
12
+ it "creates a module" do
13
13
  role = RoleContextTester.const_get(:Admin)
14
14
  refute_instance_of Class, role
15
15
  assert_kind_of Module, role
16
16
  end
17
-
18
- it 'marks the constant private' do
19
- error = assert_raises(NameError){
17
+
18
+ it "marks the constant private" do
19
+ error = assert_raises(NameError) {
20
20
  RoleContextTester::Admin
21
21
  }
22
22
  assert_match(/private constant/i, error.message)
23
23
  end
24
24
  end
25
-
26
- class WrapperRoleContext
27
- extend Surrounded::Context
28
-
29
- role :admin, :wrap do
30
-
31
- end
25
+ end
26
+
27
+ class WrapperRoleContext
28
+ extend Surrounded::Context
29
+
30
+ role :admin, :wrap do
32
31
  end
33
-
34
- describe 'wrappers' do
35
- it 'creates a wrapper' do
36
- role = WrapperRoleContext.const_get('Admin')
32
+ end
33
+
34
+ describe Surrounded::Context, ".role" do
35
+ describe "wrappers" do
36
+ it "creates a wrapper" do
37
+ role = WrapperRoleContext.const_get(:Admin)
37
38
  assert_includes(role.ancestors, SimpleDelegator)
38
39
  end
39
-
40
- it 'marks the constant private' do
41
- error = assert_raises(NameError){
40
+
41
+ it "marks the constant private" do
42
+ error = assert_raises(NameError) {
42
43
  WrapperRoleContext::Admin
43
44
  }
44
45
  assert_match(/private constant/i, error.message)
45
46
  end
46
47
  end
47
- class InterfaceContext
48
- extend Surrounded::Context
49
-
50
- initialize(:admin, :other)
51
-
52
- role :admin, :interface do
53
- def hello
54
- 'hello from admin'
55
- end
48
+ end
56
49
 
57
- def splat_args(*args)
58
- args
59
- end
50
+ class InterfaceContext
51
+ extend Surrounded::Context
60
52
 
61
- def keyword_args(**kwargs)
62
- kwargs
63
- end
53
+ initialize(:admin, :other)
64
54
 
65
- def mixed_args(*args, **kwargs)
66
- [args, kwargs]
67
- end
68
- end
69
-
70
- trigger :admin_hello do
71
- admin.hello
55
+ role :admin, :interface do
56
+ def hello
57
+ "hello from admin"
72
58
  end
73
59
 
74
- trigger :splat_args do |*args|
75
- admin.splat_args(*args)
60
+ def splat_args(*args)
61
+ args
76
62
  end
77
63
 
78
- trigger :keyword_args do |**kwargs|
79
- admin.keyword_args(**kwargs)
64
+ def keyword_args(**kwargs)
65
+ kwargs
80
66
  end
81
67
 
82
- trigger :mixed_args do |*args, **kwargs|
83
- admin.mixed_args(*args, **kwargs)
68
+ def mixed_args(*args, **kwargs)
69
+ [args, kwargs]
84
70
  end
85
71
  end
86
-
87
- class Hello
88
- include Surrounded
89
- def hello
90
- 'hello'
91
- end
72
+
73
+ trigger :admin_hello do
74
+ admin.hello
75
+ end
76
+
77
+ trigger :splat_args do |*args|
78
+ admin.splat_args(*args)
79
+ end
80
+
81
+ trigger :keyword_args do |**kwargs|
82
+ admin.keyword_args(**kwargs)
92
83
  end
93
-
94
- describe 'interfaces' do
95
- let(:context){
84
+
85
+ trigger :mixed_args do |*args, **kwargs|
86
+ admin.mixed_args(*args, **kwargs)
87
+ end
88
+ end
89
+
90
+ class Hello
91
+ include Surrounded
92
+
93
+ def hello
94
+ "hello"
95
+ end
96
+ end
97
+
98
+ describe Surrounded::Context, ".role" do
99
+ describe "interfaces" do
100
+ let(:context) {
96
101
  InterfaceContext.new(admin: Hello.new, other: Hello.new)
97
102
  }
98
- it 'sets interface objects to use interface methods before singleton methods' do
99
- assert_equal 'hello from admin', context.admin_hello
103
+ it "sets interface objects to use interface methods before singleton methods" do
104
+ assert_equal "hello from admin", context.admin_hello
100
105
  end
101
-
102
- it 'marks the inteface constant private' do
103
- error = assert_raises(NameError){
106
+
107
+ it "marks the inteface constant private" do
108
+ error = assert_raises(NameError) {
104
109
  InterfaceContext::AdminInterface
105
110
  }
106
111
  assert_match(/private constant/i, error.message)
107
112
  end
108
-
109
- it 'creates a private accessor method' do
113
+
114
+ it "creates a private accessor method" do
110
115
  assert context.respond_to?(:admin, true)
111
116
  end
112
117
 
113
- it 'works with multiple args' do
114
- assert_equal context.splat_args("one", "two"), %w[ one two ]
118
+ it "works with multiple args" do
119
+ assert_equal context.splat_args("one", "two"), %w[one two]
115
120
  end
116
121
 
117
- it 'works with multiple keyword args' do
118
- assert_equal context.keyword_args(one: "one", two: "two"), { one: "one", two: "two" }
122
+ it "works with multiple keyword args" do
123
+ assert_equal context.keyword_args(one: "one", two: "two"), {one: "one", two: "two"}
119
124
  end
120
125
 
121
- it 'works with multiple mixed args' do
122
- assert_equal context.mixed_args("one", :two, three: "three", four: "four"), [["one", :two], { three: "three", four: "four" }]
126
+ it "works with multiple mixed args" do
127
+ assert_equal context.mixed_args("one", :two, three: "three", four: "four"), [["one", :two], {three: "three", four: "four"}]
123
128
  end
124
129
  end
125
-
126
- describe 'unknown' do
127
- it 'raises an error' do
128
- class UnknownRole
129
- extend Surrounded::Context
130
- end
130
+ end
131
131
 
132
- err = _{
132
+ class UnknownRole
133
+ extend Surrounded::Context
134
+ end
135
+
136
+ describe Surrounded::Context, ".role" do
137
+ describe "unknown" do
138
+ it "raises an error" do
139
+ err = _ {
133
140
  UnknownRole.instance_eval do
134
141
  role :admin, :unknown do
135
142
  end
@@ -138,51 +145,54 @@ describe Surrounded::Context, '.role' do
138
145
  _(err.cause).must_be_kind_of NameError
139
146
  end
140
147
  end
141
-
142
- describe 'custom default' do
148
+ end
149
+
150
+ class CustomDefaultWrap
151
+ extend Surrounded::Context
152
+
153
+ self.default_role_type = :wrap
154
+
155
+ initialize(:admin, :the_test)
156
+
157
+ role :admin do
158
+ end
159
+
160
+ trigger :check_admin_type do
161
+ the_test.assert_kind_of SimpleDelegator, admin
162
+ end
163
+ end
164
+
165
+ describe Surrounded::Context, ".role" do
166
+ describe "custom default" do
143
167
  include Surrounded # the test is a role player here
144
-
145
- it 'allows the use of custom default role types' do
146
- class CustomDefaultWrap
168
+
169
+ it "allows the use of custom default role types" do
170
+ context = CustomDefaultWrap.new(admin: Object.new, the_test: self)
171
+ context.check_admin_type
172
+ end
173
+
174
+ it "allows the setting of custom default role type for all Surrounded::Contexts" do
175
+ old_default = Surrounded::Context.default_role_type
176
+ Surrounded::Context.default_role_type = :wrap
177
+
178
+ # Define the class after setting the global default so it picks up the new default
179
+ custom_global_default_class = Class.new do
147
180
  extend Surrounded::Context
148
-
149
- self.default_role_type = :wrap
150
-
181
+
151
182
  initialize(:admin, :the_test)
152
-
183
+
153
184
  role :admin do
154
185
  end
155
-
186
+
156
187
  trigger :check_admin_type do
157
188
  the_test.assert_kind_of SimpleDelegator, admin
158
189
  end
159
190
  end
160
- context = CustomDefaultWrap.new(admin: Object.new, the_test: self)
191
+
192
+ context = custom_global_default_class.new(admin: Object.new, the_test: self)
161
193
  context.check_admin_type
162
- end
163
-
164
- it 'allows the setting of custom default role type for all Surrounded::Contexts' do
165
- begin
166
- old_default = Surrounded::Context.default_role_type
167
- Surrounded::Context.default_role_type = :wrap
168
- class CustomGlobalDefault
169
- extend Surrounded::Context
170
-
171
- initialize(:admin, :the_test)
172
-
173
- role :admin do
174
- end
175
-
176
- trigger :check_admin_type do
177
- the_test.assert_kind_of SimpleDelegator, admin
178
- end
179
- end
180
-
181
- context = CustomGlobalDefault.new(admin: Object.new, the_test: self)
182
- context.check_admin_type
183
- ensure
184
- Surrounded::Context.default_role_type = old_default
185
- end
194
+ ensure
195
+ Surrounded::Context.default_role_type = old_default
186
196
  end
187
197
  end
188
198
  end