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
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 152c9c728084be8069384cf825cedf5ab827d4fd28b0710cbdd19229d8284bc7
4
- data.tar.gz: 82a50b285aa5328084481c438d78f8ed3e17ba362bcad45c14efaf5ad1bf0fc3
3
+ metadata.gz: e6cd923340dae45ac571dd98abf41be26d111f4569c59d98c27cd4e71f6204d1
4
+ data.tar.gz: a5d11c76eccb01b30fdec8aaced90571449d96c21fe4eced13e55dc1603241da
5
5
  SHA512:
6
- metadata.gz: 9f7cf841bf2c4ceeb27fd6bd2f11c4041cad7c28e1ce71574b5bbc1c201b0944a2481966b1c2349b3cbfd465a98f7627f1621fae0e0e8d2c2c9fcde42859577f
7
- data.tar.gz: aa91c16fefb0cdc19f1b597d2fffd876c2f0bce15bcbcaacb3a713570acac350d8ff434a8c3d6177d4c9e1a79c620611f012d1aff2bcd24fef10ddf696bcd13b
6
+ metadata.gz: 90659aa84b6565797f5b45fb4b637d0dfa21190dfed5366c20b586c4351ca1d0f02fdc5f8d6c45620ac6c9b36dccac28a842ce74b93a2d0a9258297db3d9e0e4
7
+ data.tar.gz: 4831ec1fe6a7dda8a9578776ecb0b2e2030ff37490d15f7e7f35351253bfe7f2c52c9ae1aa8fb7172cb471236b3d5c639f7eae8ef8c5510668a56542ba0fe014
data/Changelog.md CHANGED
@@ -1,28 +1,19 @@
1
- # Change Log
1
+ # Changelog
2
2
 
3
3
  All notable changes to this project will be documented in this file.
4
4
 
5
- ## [1.1.0]
5
+ The format is based on [Keep a Changelog](http://keepachangelog.com/)
6
+ and this project adheres to [Semantic Versioning](http://semver.org/).
6
7
 
7
- - Dropped support for Ruby below 2.7 to take advantage of the ellipsis for argument forwarding
8
- - Memoize the Negotiator methods for interface
8
+ ## [1.1.1] - 2025-10-17
9
9
 
10
- ## [1.0.1]
10
+ ### Changed
11
11
 
12
- - Fix a bug where shortcut_triggers would not work with keyword initialize
12
+ - Version and changelog management with Reissue. (c919a3a)
13
+ - Set the gemspec to use a file list rather than depending on git (69b9a43)
14
+ - Update singularize_name to duplicate a string before altering the value. (3487d0d)
15
+ - Alter the list of identity methods in Negotiator to include __id__. (b98fb5a)
13
16
 
14
- ## [1.0.0]
17
+ ### Removed
15
18
 
16
- - Drop deprecations around Context initialize method. It now requires keyword arguments. Non-keyword argumennts may be used with initialize_without_keywords
17
- - Remove code supporting exception cause it InvalidRoleType prior to ruby 2.1
18
-
19
- ## [0.9.11]
20
-
21
- - Rely on the standard library Forwardable to setup how the RoleMap forwards messages to the container.
22
- - Update RoleMap role_player? method to rescue from StandardError, a non-implementation-specific exception.
23
- - Move to using triad 0.3.0 which relies on concurrent-ruby 0.9+ and moves off of thread_safe 0.3.5
24
-
25
- ## [0.9.10]
26
-
27
- - Do something with name collisions when a role player has an existing method of another role in the context.
28
- - Move InvalidRoleType exception under the host context class namespace. This allows you to rescue from your own namespace.
19
+ - Code Climate and Pull Review configuration. (46f0057)
data/LICENSE.txt CHANGED
@@ -1,4 +1,4 @@
1
- Copyright (c) 2013-2022 'Jim Gay'
1
+ Copyright (c) 2013-2025 'Jim Gay'
2
2
 
3
3
  MIT License
4
4
 
data/README.md CHANGED
@@ -1,8 +1,8 @@
1
1
  # ![Surrounded](http://saturnflyer.github.io/surrounded/images/surrounded.png "Surrounded")
2
+
2
3
  ## Be in control of business logic.
3
4
 
4
5
  [![Build Status](https://github.com/saturnflyer/surrounded/actions/workflows/test.yml/badge.svg)](https://github.com/saturnflyer/surrounded/actions)
5
- [![Code Climate](https://codeclimate.com/github/saturnflyer/surrounded.png)](https://codeclimate.com/github/saturnflyer/surrounded)
6
6
 
7
7
  Surrounded is designed to help you better manage your business logic by keeping cohesive behaviors together. Bring objects together to implement your use cases and gain behavior only when necessary.
8
8
 
@@ -920,7 +920,7 @@ end
920
920
 
921
921
  If you'd like to use a special approach for just a single role, you may do that too.
922
922
 
923
- When applying behaviors from a role to your role players, your Surrounded context will first look for a method named `"apply_behavior_#{role}"`. Define your own method and set it to accept 2 arguments: the role constant and the role player.
923
+ When applying behaviors from a role to your role players, your Surrounded context will first look for a method named `"apply_behavior_#{role}"`. Define your own method and set it to accept 2 arguments: the role constant and the role player.
924
924
 
925
925
  ```ruby
926
926
  class MyCustomContext
@@ -982,7 +982,6 @@ Lets say that you wish to create a context as below, intending to use instances
982
982
  postcode.send
983
983
  end
984
984
 
985
- end
986
985
  role :postcode do
987
986
  def send
988
987
  # do things...
@@ -991,6 +990,7 @@ Lets say that you wish to create a context as below, intending to use instances
991
990
  end
992
991
  end
993
992
  ```
993
+
994
994
  When you call the `:send` trigger you are likely to be greeted with an `NoMethodError` exception. The reason for this is that there is a name collision between `Postcode#country`, and the `:country` role in the `SendAParcel` context. Where a name collision exists, the method in the role player overrides that of the calling class and you get unexpected results.
995
995
 
996
996
  To address this issue, use `on_name_collision` to specify the name of a method to use when collisions are found:
data/Rakefile CHANGED
@@ -1,17 +1,24 @@
1
1
  require "bundler/gem_tasks"
2
2
 
3
- require 'rake/testtask'
3
+ require "rake/testtask"
4
4
 
5
5
  Rake::TestTask.new do |t|
6
6
  t.libs << "test"
7
- t.test_files = FileList['test/*_test.rb']
8
- t.ruby_opts = ["-w"]
7
+ t.test_files = FileList["test/*_test.rb"]
9
8
  t.verbose = true
9
+ t.warning = true
10
10
  end
11
- task :default => :test
12
11
 
12
+ task default: :test
13
+
14
+ require "reissue/gem"
15
+
16
+ Reissue::Task.create :reissue do |task|
17
+ task.version_file = "lib/surrounded/version.rb"
18
+ task.fragment = :git
19
+ end
13
20
 
14
21
  # task :mutant, [:class] do |task, args|
15
22
  # klass = args[:class] || 'Surrounded'
16
23
  # sh "bundle exec mutant --include lib --require surrounded --use minitest #{klass}"
17
- # end
24
+ # end
@@ -2,33 +2,34 @@ module Surrounded
2
2
  module Context
3
3
  class AccessError < ::StandardError; end
4
4
  end
5
+
5
6
  module AccessControl
6
7
  def self.extended(base)
7
8
  base.send(:include, AccessMethods)
8
9
  Surrounded::Exceptions.define(base, exceptions: :AccessError)
9
10
  end
10
-
11
+
11
12
  private
12
-
13
+
13
14
  def disallow(*names, &block)
14
15
  names.map do |name|
15
16
  define_access_method(name, &block)
16
17
  end
17
18
  end
18
- alias guard disallow
19
-
19
+ alias_method :guard, :disallow
20
+
20
21
  def trigger_return_content(name, *args, &block)
21
22
  %{
22
23
 
23
24
  method_restrictor = "disallow_#{name}?"
24
25
  if self.respond_to?(method_restrictor, true) && self.send(method_restrictor)
25
- raise ::#{self.to_s}::AccessError.new("access to #{self.name}##{name} is not allowed")
26
+ raise ::#{self}::AccessError.new("access to #{self.name}##{name} is not allowed")
26
27
  end
27
28
 
28
29
  #{super}
29
30
  }
30
31
  end
31
-
32
+
32
33
  def define_access_method(name, &block)
33
34
  mod = Module.new
34
35
  mod.class_eval {
@@ -42,26 +43,26 @@ module Surrounded
42
43
  const_set("SurroundedAccess#{name}", mod)
43
44
  include mod
44
45
  end
45
-
46
+
46
47
  module AccessMethods
47
48
  # Return a Set of all defined triggers regardless of any disallow blocks
48
49
  def all_triggers
49
50
  self.class.triggers
50
51
  end
51
-
52
+
52
53
  # Return a Set of triggers which may be run according to any restrictions defined
53
54
  # in disallow blocks.
54
55
  def triggers
55
- all_triggers.select {|name|
56
+ all_triggers.select { |name|
56
57
  allow?(name)
57
58
  }.to_set
58
59
  end
59
60
 
60
61
  # Ask if the context will allow access to a trigger given the current players.
61
62
  def allow?(name)
62
- raise NoMethodError, %{undefined method `#{name}' for #{self.inspect}} unless self.respond_to?(name)
63
+ raise NoMethodError, %(undefined method `#{name}' for #{inspect}) unless respond_to?(name)
63
64
  predicate = "disallow_#{name}?"
64
- !self.respond_to?(predicate) || !self.public_send(predicate)
65
+ !respond_to?(predicate) || !public_send(predicate)
65
66
  end
66
67
  end
67
68
  end
@@ -1,27 +1,27 @@
1
1
  module Surrounded
2
2
  module Context
3
3
  module Forwarding
4
- def forward_trigger(receiver, message, alternate=message)
5
- raise(ArgumentError, %{you may not forward '%{m}`} % {m: message}) if ['__id__','__send__'].include?(message.to_s)
6
- trigger alternate do |*args, &block|
7
- self.send(receiver).public_send(message,*args, &block)
4
+ def forward_trigger(receiver, message, alternate = message)
5
+ raise(ArgumentError, %(you may not forward '%{m}`) % {m: message}) if ["__id__", "__send__"].include?(message.to_s)
6
+ trigger alternate do |*args, **kwargs, &block|
7
+ send(receiver).public_send(message, *args, **kwargs, &block)
8
8
  end
9
9
  end
10
-
10
+
11
11
  def forward_triggers(receiver, *messages)
12
12
  messages.each do |message|
13
13
  forward_trigger(receiver, message)
14
14
  end
15
15
  end
16
-
16
+
17
17
  def forwarding(hash)
18
18
  hash.each { |messages, receiver|
19
19
  forward_triggers(receiver, *messages)
20
20
  }
21
21
  end
22
-
23
- alias forward forward_trigger
24
- alias forwards forward_triggers
22
+
23
+ alias_method :forward, :forward_trigger
24
+ alias_method :forwards, :forward_triggers
25
25
  end
26
26
  end
27
- end
27
+ end
@@ -2,19 +2,20 @@ module Surrounded
2
2
  module Context
3
3
  module Initializing
4
4
  extend Seclusion
5
+
5
6
  # Shorthand for creating an instance level initialize method which
6
7
  # handles the mapping of the given arguments to their named role.
7
8
  def initialize_without_keywords(*setup_args, &block)
8
- parameters = setup_args.join(',')
9
+ parameters = setup_args.join(",")
9
10
  default_initializer(parameters, setup_args, &block)
10
11
  end
11
12
 
12
13
  def initialize(*setup_args, &block)
13
- parameters = setup_args.map{|a| "#{a}:"}.join(',')
14
+ parameters = setup_args.map { |a| "#{a}:" }.join(",")
14
15
  default_initializer(parameters, setup_args, &block)
15
16
  end
16
- alias keyword_initialize initialize
17
- alias initialize_with_keywords keyword_initialize
17
+ alias_method :keyword_initialize, :initialize
18
+ alias_method :initialize_with_keywords, :keyword_initialize
18
19
 
19
20
  def initializer_block
20
21
  @initializer_block
@@ -31,13 +32,14 @@ module Surrounded
31
32
  line = __LINE__; mod.class_eval %{
32
33
  def initialize(#{params})
33
34
  @role_map = role_mapper_class.new
34
- @initializer_arguments = Hash[#{setup_args.to_s}.zip([#{setup_args.join(',')}])]
35
+ @initializer_arguments = Hash[#{setup_args}.zip([#{setup_args.join(",")}])]
35
36
  map_roles(@initializer_arguments)
36
37
  self.class.apply_initializer_block(self)
37
38
  end
38
39
  }, __FILE__, line
39
- const_set("ContextInitializer", mod)
40
+ const_set(:ContextInitializer, mod)
40
41
  include mod
42
+
41
43
  private_attr_reader :initializer_arguments
42
44
  end
43
45
  end
@@ -1,56 +1,56 @@
1
1
  module Surrounded
2
2
  module Context
3
- class NameCollisionError <::StandardError; end
4
- module NameCollisionDetector
3
+ class NameCollisionError < ::StandardError; end
5
4
 
5
+ module NameCollisionDetector
6
6
  attr_reader :handler
7
7
 
8
8
  def self.extended(base)
9
9
  base.send :include, NameCollisionHandler
10
10
  Surrounded::Exceptions.define(base, exceptions: :NameCollisionError)
11
11
  end
12
-
12
+
13
13
  def on_name_collision(method_name)
14
14
  @handler = method_name
15
15
  end
16
16
 
17
17
  module NameCollisionHandler
18
-
19
18
  private
20
-
19
+
21
20
  def detect_collisions(role_object_map)
22
21
  if handler
23
22
  handle_collisions(collision_warnings(role_object_map))
24
23
  end
25
24
  end
26
-
25
+
27
26
  def collision_warnings(role_object_map)
28
- role_object_map.select{|role, object|
27
+ role_object_map.select { |role, object|
29
28
  ![object.methods & role_object_map.keys].flatten.empty?
30
- }.map{|role, object|
31
- role_collision_message(role,(object.methods & role_object_map.keys).sort)
29
+ }.map { |role, object|
30
+ role_collision_message(role, (object.methods & role_object_map.keys).sort)
32
31
  }.join("\n")
33
32
  end
34
-
33
+
35
34
  def handle_collisions(collisions)
36
35
  handler_args = [collisions]
37
36
  if handler == :raise
38
37
  handler_args.unshift self.class::NameCollisionError
39
38
  end
40
-
39
+
41
40
  handler_method.call(*handler_args)
42
41
  end
43
-
42
+
44
43
  def role_collision_message(role, colliding_method_names)
45
44
  "#{role} has name collisions with #{colliding_method_names}"
46
45
  end
47
-
48
- def nothing(*); end
46
+
47
+ def nothing(*)
48
+ end
49
49
 
50
50
  def handler
51
51
  self.class.handler
52
52
  end
53
-
53
+
54
54
  def handler_method
55
55
  if handler.respond_to?(:call)
56
56
  handler
@@ -59,10 +59,10 @@ module Surrounded
59
59
  elsif self.class.respond_to?(handler, true)
60
60
  self.class.method(handler)
61
61
  else
62
- raise ArgumentError, %{your name collision handler was set to `#{handler}' but there is no instance nor class method of that name}
62
+ raise ArgumentError, %(your name collision handler was set to `#{handler}' but there is no instance nor class method of that name)
63
63
  end
64
64
  end
65
65
  end
66
66
  end
67
67
  end
68
- end
68
+ end
@@ -14,25 +14,24 @@ module Surrounded
14
14
  # For each method in the module, directly forward to the wrapped object to
15
15
  # circumvent method_missing
16
16
  mod.instance_methods(false).each do |meth|
17
- num = __LINE__; klass.class_eval %{
17
+ klass.class_eval <<~MOD, __FILE__, __LINE__ + 1
18
18
  def #{meth}(...)
19
19
  @#{meth}_method ||= __behaviors__.instance_method(:#{meth}).bind(@object)
20
20
  @#{meth}_method.call(...)
21
21
  end
22
- }, __FILE__, num
22
+ MOD
23
23
  end
24
24
  klass
25
25
  end
26
26
  end
27
27
 
28
-
29
- identity = %w[__send__ object_id equal?]
28
+ identity = %w[__send__ __id__ object_id equal?]
30
29
  method_access = %w[respond_to? method __behaviors__]
31
30
 
32
- reserved_methods = (identity + method_access).join('|')
31
+ reserved_methods = (identity + method_access).join("|")
33
32
 
34
33
  # Remove all methods except the reserved methods
35
- instance_methods.reject{ |m|
34
+ instance_methods.reject { |m|
36
35
  m.to_s =~ /#{reserved_methods}/
37
36
  }.each do |meth|
38
37
  undef_method meth
@@ -52,7 +51,7 @@ module Surrounded
52
51
  self
53
52
  end
54
53
  # These only differ in the message they send
55
- alias remove_context store_context
54
+ alias_method :remove_context, :store_context
56
55
 
57
56
  def initialize(object)
58
57
  @object = object
@@ -62,7 +61,7 @@ module Surrounded
62
61
  @object.send(meth, ...)
63
62
  end
64
63
 
65
- def respond_to_missing?(meth, include_private=false)
64
+ def respond_to_missing?(meth, include_private = false)
66
65
  @object.respond_to?(meth, include_private)
67
66
  end
68
67
  end
@@ -10,7 +10,7 @@ module Surrounded
10
10
  end
11
11
 
12
12
  # Define behaviors for your role players
13
- def role(name, type=default_role_type, &block)
13
+ def role(name, type = default_role_type, &block)
14
14
  if type == :module
15
15
  mod_name = RoleName(name)
16
16
  mod = Module.new(&block).send(:include, ::Surrounded)
@@ -26,7 +26,7 @@ module Surrounded
26
26
 
27
27
  # Create a named behavior for a role using the standard library SimpleDelegator.
28
28
  def wrap(name, &block)
29
- require 'delegate'
29
+ require "delegate"
30
30
  wrapper_name = RoleName(name)
31
31
  klass = private_const_set(wrapper_name, Class.new(SimpleDelegator, &block))
32
32
  klass.send(:include, Surrounded)
@@ -36,7 +36,7 @@ module Surrounded
36
36
  # Create a named behavior for a role using the standard library DelegateClass.
37
37
  # This ties the implementation of the role to a specific class or module API.
38
38
  def delegate_class(name, class_name, &block)
39
- require 'delegate'
39
+ require "delegate"
40
40
  wrapper_name = RoleName(name)
41
41
  klass = private_const_set(wrapper_name, DelegateClass(Object.const_get(class_name.to_s)))
42
42
  klass.class_eval(&block)
@@ -53,19 +53,19 @@ module Surrounded
53
53
  # access them from any of its methods.
54
54
  def interface(name, &block)
55
55
  # AdminInterface
56
- interface_name = RoleName(name, 'Interface')
56
+ interface_name = RoleName(name, "Interface")
57
57
  behavior = private_const_set(interface_name, Module.new(&block))
58
58
 
59
- require 'surrounded/context/negotiator'
59
+ require "surrounded/context/negotiator"
60
60
  # Admin
61
61
  private_const_set(RoleName(name), Negotiator.for_role(behavior))
62
62
  end
63
63
 
64
64
  private
65
- def RoleName(text, suffix=nil)
65
+
66
+ def RoleName(text, suffix = nil)
66
67
  RoleName.new(text, suffix)
67
68
  end
68
-
69
69
  end
70
70
  end
71
71
  end
@@ -1,5 +1,5 @@
1
- require 'triad'
2
- require 'forwardable'
1
+ require "triad"
2
+ require "forwardable"
3
3
  module Surrounded
4
4
  module Context
5
5
  class RoleMap
@@ -8,19 +8,17 @@ module Surrounded
8
8
  class << self
9
9
  # Get the role map container and provide an alternative if desired
10
10
  # Ex: RoleMap.from_base(SomeCustomContainer)
11
- def from_base(klass=::Triad)
11
+ def from_base(klass = ::Triad)
12
12
  unless const_defined?(:Container)
13
13
  role_mapper = Class.new(self)
14
- role_mapper.container_class=(klass)
14
+ role_mapper.container_class = (klass)
15
15
  Surrounded::Exceptions.define(role_mapper, exceptions: :ItemNotPresent, namespace: klass)
16
16
  const_set(:Container, role_mapper)
17
17
  end
18
18
  const_get(:Container)
19
19
  end
20
20
 
21
- def container_class=(klass)
22
- @container_class = klass
23
- end
21
+ attr_writer :container_class
24
22
  end
25
23
 
26
24
  def_delegators :container, :update, :each, :values, :keys
@@ -37,7 +35,7 @@ module Surrounded
37
35
  # Check if an object is playing a role in this map
38
36
  def role_player?(object)
39
37
  !values(object).empty?
40
- rescue self.container.class::ItemNotPresent
38
+ rescue container.class::ItemNotPresent
41
39
  false
42
40
  end
43
41
 
@@ -1,24 +1,23 @@
1
1
  module Surrounded
2
2
  module Context
3
3
  module TriggerControls
4
-
5
4
  # Provides a Set of all available trigger methods where
6
5
  # behaviors will be applied to the roles before execution
7
6
  # and removed afterward.
8
7
  def triggers
9
8
  @triggers.dup
10
9
  end
11
-
10
+
12
11
  def store_trigger(*names)
13
12
  @triggers.merge(names)
14
13
  end
15
-
14
+
16
15
  # Creates a context instance method which will apply behaviors to role players
17
16
  # before execution and remove the behaviors after execution.
18
17
  #
19
18
  # Alternatively you may define your own methods then declare them as triggers
20
19
  # afterward.
21
- #
20
+ #
22
21
  # Example:
23
22
  # trigger :some_event do
24
23
  # # code here
@@ -41,7 +40,7 @@ module Surrounded
41
40
  store_trigger(name)
42
41
  end
43
42
  end
44
-
43
+
45
44
  def convert_method_to_trigger(name)
46
45
  unless triggers.include?(name) || name.nil?
47
46
  alias_method :"__trigger_#{name}", :"#{name}"
@@ -53,7 +52,7 @@ module Surrounded
53
52
  end
54
53
 
55
54
  def define_trigger(name)
56
- line = __LINE__; self.class_eval %{
55
+ class_eval <<~MOD, __FILE__, __LINE__ + 1
57
56
  def #{name}(...)
58
57
  begin
59
58
  apply_behaviors
@@ -64,24 +63,23 @@ module Surrounded
64
63
  remove_behaviors
65
64
  end
66
65
  end
67
- }, __FILE__, line
66
+ MOD
68
67
  end
69
-
68
+
70
69
  def trigger_return_content(name)
71
70
  if method_defined?(name)
72
- %{super}
71
+ %(super)
73
72
  else
74
73
  %{self.send("__trigger_#{name}", ...)}
75
74
  end
76
75
  end
77
-
78
-
76
+
79
77
  def define_trigger_action(*name_and_args, &block)
80
78
  trigger_action_module.send(:define_method, *name_and_args, &block)
81
79
  end
82
-
80
+
83
81
  def trigger_action_module
84
- self.const_get('TriggerMethods', false)
82
+ const_get(:TriggerMethods, false)
85
83
  end
86
84
  end
87
85
  end