casting 1.0.1 → 1.0.3

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 87f6f44b2f7597c28ab23eb2d02fd06479558ac075f3b6646cd583ea98e5f945
4
- data.tar.gz: cdf55addbcdbaf848d4991fe8562b5bbeb50ea9b3fde1548f210ebb76d761186
3
+ metadata.gz: 3e9ce2a6479f584071216d9aa62c7f076525325295cbd4df491dd6cbf4ffad39
4
+ data.tar.gz: 3c1475f0c68d62ac2ba37c542b5c7d0a8c6fddad91a88a7097c03dcdaa02f5d9
5
5
  SHA512:
6
- metadata.gz: 71d6eac4b57b571f8c593606f645477402dd9557081ac684c9c5117257e111916b17ec830836cfe9063acae7572aef5b96e20d5219558bf466769119a95b42a1
7
- data.tar.gz: b81bf24dc30d94cbb520eb302f5173efe2f64b19b062a128071c30833df2f92c4a643b47717fa3092afdc2f20cc15a78631b2fa0fab1a80a8e6e9ed18c7bddc9
6
+ metadata.gz: 4942f847d1219c074e2794e8079a22c37bccfb0f011502944835c2b4b1aa1413f957fba526545fc66ea3d53f35e0cad5de206ec2560be51e2b4123624161f42f
7
+ data.tar.gz: c8b62a94bade49af44f49c49fdf1bca3075dfc68a7b65d57f31f4e6cd201fa32915ad1e5f7c6491806119000e3d350233331fcf5bfca94e8567c1c46b319f388
data/README.md CHANGED
@@ -1,10 +1,9 @@
1
1
  # Casting
2
2
 
3
- [![Code Climate](https://codeclimate.com/github/saturnflyer/casting.png)](https://codeclimate.com/github/saturnflyer/casting)
4
- [![Test Coverage](https://codeclimate.com/github/saturnflyer/casting/badges/coverage.svg)](https://codeclimate.com/github/saturnflyer/casting/coverage)
5
3
  [![Gem Version](https://badge.fury.io/rb/casting.png)](http://badge.fury.io/rb/casting)
6
4
 
7
5
  ## Add behavior to your objects without using extend
6
+
8
7
  Do it for the life of the object or only for the life of a block of code.
9
8
 
10
9
  Casting gives you real delegation that flattens your object structure compared to libraries
@@ -53,7 +52,7 @@ end
53
52
  actor = Actor.new
54
53
  ```
55
54
 
56
- Your objects will have a few additional methods: `delegation`, `cast`, and if you do not *already* have it defined (from another library, for example): `delegate`. The `delegate` method is aliased to `cast`.
55
+ Your objects will have a few additional methods: `delegation`, `cast`, and if you do not _already_ have it defined (from another library, for example): `delegate`. The `delegate` method is aliased to `cast`.
57
56
 
58
57
  Then you may delegate a method to an attendant object:
59
58
 
@@ -327,11 +326,11 @@ module Special
327
326
  def self.cast_object(obj)
328
327
  obj.instance_variable_set(:@special_value, 'this is special!')
329
328
  end
330
-
329
+
331
330
  def self.uncast_object(obj)
332
331
  obj.remove_instance_variable(:@special_value)
333
332
  end
334
-
333
+
335
334
  def special_behavior
336
335
  "#{self.name} thinks... #{@special_value}"
337
336
  end
@@ -345,6 +344,47 @@ object.uncast
345
344
 
346
345
  You'll be able to leave your objects as if they were never touched by the module where you defined your behavior.
347
346
 
347
+ ## It doesn't work!
348
+
349
+ You might be trying to override existing methods. Casting can help you apply behavior to an object using `delegate_missing_methods` but that depends on the methods being missing. In other words, if you have an `as_json` method that you want to change with a module, you won't be able to just `cast_as(MyJsonModule)` and have the `as_json` method from it be picked up because that will never hit `method_missing`.
350
+
351
+ If you want to override an existing method, you must do so explicitly.
352
+
353
+ This will _not_ work:
354
+
355
+ ```ruby
356
+ module MyJsonModule
357
+ def as_json
358
+ super.merge({ extra: 'details' })
359
+ end
360
+ end
361
+ some_object.cast_as(MyJsonModule)
362
+ some_object.as_json
363
+ ```
364
+
365
+ Instead, you'll need to explicitly override existing methods:
366
+
367
+ ```ruby
368
+ some_object.cast(:as_json, MyJsonModule)
369
+ ```
370
+
371
+ ## How can I speed it up?
372
+
373
+ Are you looping over lots of objects and want see better performance?
374
+
375
+ If you want to make things a bit faster, you can prepare the method delegation ahead of time and change the client object.
376
+
377
+ ```ruby
378
+ prepared_delegation = some_object.delegation(:some_delegated_method).to(MySpecialModule)
379
+ # Some looping code
380
+ big_list_of_objects.each do |object|
381
+ prepared_delegation.client = object
382
+ prepared_delegation.call
383
+ end
384
+ ```
385
+
386
+ Preparing the delegated method like this will probably speed things up for you but be sure to verify for yourself.
387
+
348
388
  ## Installation
349
389
 
350
390
  If you are using Bundler, add this line to your application's Gemfile:
data/Rakefile CHANGED
@@ -1,12 +1,19 @@
1
1
  #!/usr/bin/env rake
2
2
  require "bundler/gem_tasks"
3
- require 'rake/testtask'
3
+ require "rake/testtask"
4
4
 
5
5
  Rake::TestTask.new do |t|
6
- t.libs << 'test'
7
- t.test_files = FileList['test/*_test.rb']
6
+ t.libs << "test"
7
+ t.test_files = FileList["test/*_test.rb"]
8
8
  t.ruby_opts = ["-w"]
9
9
  t.verbose = true
10
10
  end
11
11
 
12
- task :default => :test
12
+ require "reissue/gem"
13
+
14
+ Reissue::Task.create do |task|
15
+ task.version_file = "lib/casting/version.rb"
16
+ task.fragment = :git
17
+ end
18
+
19
+ task default: :test
@@ -1,22 +1,21 @@
1
- require 'casting/delegation'
2
- require 'casting/missing_method_client'
3
- require 'casting/missing_method_client_class'
1
+ require "casting/delegation"
2
+ require "casting/missing_method_client"
3
+ require "casting/missing_method_client_class"
4
4
 
5
5
  module Casting
6
6
  module Client
7
-
8
7
  def self.included(base)
9
8
  def base.delegate_missing_methods(*which)
10
9
  Casting::Client.set_delegation_strategy(self, *which.reverse)
11
10
  end
12
11
 
13
- unless base.method_defined?('delegate')
12
+ unless base.method_defined?(:delegate)
14
13
  add_delegate_method_to(base)
15
14
  end
16
15
  end
17
16
 
18
17
  def self.extended(base)
19
- unless base.respond_to?('delegate')
18
+ unless base.respond_to?(:delegate)
20
19
  add_delegate_method_to(base.singleton_class)
21
20
  end
22
21
  end
@@ -31,28 +30,28 @@ module Casting
31
30
  end
32
31
 
33
32
  def delegate_missing_methods(*which)
34
- Casting::Client.set_delegation_strategy(self.singleton_class, *which.reverse)
33
+ Casting::Client.set_delegation_strategy(singleton_class, *which.reverse)
35
34
  end
36
35
 
37
36
  private
38
37
 
39
38
  def validate_attendant(attendant)
40
39
  if attendant == self
41
- raise Casting::InvalidAttendant.new('client can not delegate to itself')
40
+ raise Casting::InvalidAttendant.new("client can not delegate to itself")
42
41
  end
43
42
  end
44
43
 
45
44
  def self.set_delegation_strategy(base, *which)
46
45
  which = [:instance] if which.empty?
47
- which.map!{|selection|
48
- selection == :instance && selection = self.method(:set_method_missing_client)
49
- selection == :class && selection = self.method(:set_method_missing_client_class)
46
+ which.map! { |selection|
47
+ selection == :instance && selection = method(:set_method_missing_client)
48
+ selection == :class && selection = method(:set_method_missing_client_class)
50
49
  selection
51
- }.map{|meth| meth.call(base) }
50
+ }.map { |meth| meth.call(base) }
52
51
  end
53
52
 
54
53
  def self.add_delegate_method_to(base)
55
- base.class_eval{ alias_method :delegate, :cast }
54
+ base.class_eval { alias_method :delegate, :cast }
56
55
  end
57
56
 
58
57
  def self.set_method_missing_client(base)
@@ -29,7 +29,6 @@
29
29
  #
30
30
  module Casting
31
31
  module Context
32
-
33
32
  def self.extended(base)
34
33
  base.send(:include, InstanceMethods)
35
34
  end
@@ -38,26 +37,21 @@ module Casting
38
37
  attr_reader(*setup_args)
39
38
  private(*setup_args)
40
39
 
41
- if block
42
- define_method(:__custom_initialize, &block)
43
- else
44
- define_method(:__custom_initialize) do; end
45
- end
40
+ define_method(:__custom_initialize, &(block || proc {}))
46
41
 
47
42
  mod = Module.new
48
- line = __LINE__; string = %<
49
- def initialize(#{setup_args.map{|name| "#{name}:" }.join(',')})
43
+ mod.class_eval <<~INIT, __FILE__, __LINE__ + 1
44
+ def initialize(#{setup_args.map { |name| "#{name}:" }.join(",")})
50
45
  @assignments = []
51
46
  #{setup_args.map do |name|
52
- ["assign(",name,", '",name,"')"].join
47
+ ["assign(", name, ", '", name, "')"].join
53
48
  end.join("\n")}
54
49
  __custom_initialize
55
50
  Thread.current[:context] = self
56
51
  end
57
52
  attr_reader :assignments
58
- >
59
- mod.class_eval string, __FILE__, line
60
- const_set('Initializer', mod)
53
+ INIT
54
+ const_set(:Initializer, mod)
61
55
  include mod
62
56
  end
63
57
 
@@ -73,7 +67,7 @@ module Casting
73
67
  # Keep track of objects and their behaviors
74
68
  def assign(object, role_name)
75
69
  instance_variable_set("@#{role_name}", object)
76
- self.assignments << [object, self.role_for(role_name)]
70
+ assignments << [object, role_for(role_name)]
77
71
  end
78
72
 
79
73
  def contains?(obj)
@@ -91,12 +85,12 @@ module Casting
91
85
 
92
86
  # Find the first assigned role which implements a response for the given method name
93
87
  def role_implementing(object, method_name)
94
- assigned_roles(object).find{|role| role.method_defined?(method_name) } || raise(NoMethodError, "unknown method '#{method_name}' expected for #{object}")
88
+ assigned_roles(object).find { |role| role.method_defined?(method_name) } || raise(NoMethodError, "unknown method '#{method_name}' expected for #{object}")
95
89
  end
96
90
 
97
91
  # Get the roles for the given object
98
92
  def assigned_roles(object)
99
- assignments.select{|pair|
93
+ assignments.select { |pair|
100
94
  pair.first == object
101
95
  }.map(&:last)
102
96
  end
@@ -104,7 +98,8 @@ module Casting
104
98
  # Get the behavior module for the named role.
105
99
  # This role constant for special_person is SpecialPerson.
106
100
  def role_for(name)
107
- role_name = name.to_s.gsub(/(?:^|_)([a-z])/) { $1.upcase }
101
+ # Convert snake_case to CamelCase
102
+ role_name = name.to_s.split('_').map(&:capitalize).join
108
103
  self.class.const_get(role_name)
109
104
  rescue NameError
110
105
  Module.new
@@ -1,5 +1,4 @@
1
1
  module Casting
2
-
3
2
  class MissingAttendant < StandardError
4
3
  def message
5
4
  "You must set your attendant object using `to'."
@@ -9,7 +8,6 @@ module Casting
9
8
  class InvalidAttendant < StandardError; end
10
9
 
11
10
  class Delegation
12
-
13
11
  def self.prepare(delegated_method_name, client, &block)
14
12
  new(delegated_method_name: delegated_method_name, client: client, &block)
15
13
  end
@@ -46,41 +44,42 @@ module Casting
46
44
  def call(*args, **kwargs, &block)
47
45
  raise MissingAttendant.new unless attendant
48
46
 
49
- call_args = if args && !args.empty?
50
- args
51
- elsif @arguments && !@arguments.empty?
52
- @arguments
53
- end
54
- call_kwargs = if kwargs && !kwargs.empty?
55
- kwargs
56
- elsif @keyword_arguments && !@keyword_arguments.empty?
57
- @keyword_arguments
58
- end
59
-
60
- call_block = block || @block
61
- if call_args
62
- if call_kwargs
63
- bound_method.call(*call_args, **call_kwargs, &call_block)
64
- else
65
- bound_method.call(*call_args, &call_block)
66
- end
47
+ call_args = positional_arguments(args)
48
+ call_kwargs = keyword_arguments(kwargs)
49
+ call_block = block_argument(&block)
50
+
51
+ case
52
+ when call_args && call_kwargs
53
+ bound_method.call(*call_args, **call_kwargs, &call_block)
54
+ when call_args
55
+ bound_method.call(*call_args, &call_block)
56
+ when call_kwargs
57
+ bound_method.call(**call_kwargs, &call_block)
67
58
  else
68
- if call_kwargs
69
- bound_method.call(**call_kwargs, &call_block)
70
- else
71
- bound_method.call(&call_block)
72
- end
59
+ bound_method.call(&call_block)
73
60
  end
74
61
  end
75
62
 
76
63
  private
77
64
 
65
+ def block_argument(&block)
66
+ block || @block
67
+ end
68
+
69
+ def positional_arguments(options)
70
+ return options unless options.empty?
71
+ @arguments
72
+ end
73
+
74
+ def keyword_arguments(options)
75
+ return options unless options.empty?
76
+ @keyword_arguments
77
+ end
78
+
78
79
  def bound_method
79
- begin
80
- delegated_method.bind(client)
81
- rescue TypeError
82
- raise TypeError.new("`to' argument must be a module or an object with #{delegated_method_name} defined in a module")
83
- end
80
+ delegated_method.bind(client)
81
+ rescue TypeError
82
+ raise TypeError.new("`to' argument must be a module or an object with #{delegated_method_name} defined in a module")
84
83
  end
85
84
 
86
85
  def method_module
@@ -92,13 +91,12 @@ module Casting
92
91
 
93
92
  def delegated_method
94
93
  if Module === attendant
95
- attendant.instance_method(delegated_method_name)
94
+ attendant
96
95
  else
97
- attendant.method(delegated_method_name).owner.instance_method(delegated_method_name)
98
- end
96
+ attendant.method(delegated_method_name).owner
97
+ end.instance_method(delegated_method_name)
99
98
  rescue NameError => e
100
- raise InvalidAttendant.new(e.message)
99
+ raise InvalidAttendant, e.message
101
100
  end
102
-
103
101
  end
104
102
  end
data/lib/casting/enum.rb CHANGED
@@ -1,7 +1,9 @@
1
1
  module Casting
2
2
  module Enum
3
+ extend self
4
+
3
5
  def enum(collection, *behaviors)
4
- enum = Enumerator.new do |yielder|
6
+ Enumerator.new do |yielder|
5
7
  collection.each do |item|
6
8
  yielder.yield(item.cast_as(*behaviors))
7
9
  end
@@ -1,19 +1,19 @@
1
1
  module Casting
2
2
  module MethodConsolidator
3
- def methods(all=true)
3
+ def methods(all = true)
4
4
  (super + delegated_methods(all)).uniq
5
5
  end
6
6
 
7
- def public_methods(include_super=true)
7
+ def public_methods(include_super = true)
8
8
  (super + delegated_public_methods(include_super)).uniq
9
9
  end
10
10
 
11
- def protected_methods(include_super=true)
11
+ def protected_methods(include_super = true)
12
12
  (super + delegated_protected_methods(include_super)).uniq
13
13
  end
14
14
 
15
- def private_methods(include_super=true)
15
+ def private_methods(include_super = true)
16
16
  (super + delegated_private_methods(include_super)).uniq
17
17
  end
18
18
  end
19
- end
19
+ end
@@ -1,8 +1,7 @@
1
- require 'casting/method_consolidator'
1
+ require "casting/method_consolidator"
2
2
 
3
3
  module Casting
4
4
  module MissingMethodClient
5
-
6
5
  def cast_as(*attendants)
7
6
  attendants.each do |attendant|
8
7
  validate_attendant(attendant)
@@ -12,7 +11,7 @@ module Casting
12
11
  self
13
12
  end
14
13
 
15
- def uncast(count=1)
14
+ def uncast(count = 1)
16
15
  count.times do
17
16
  attendant = __delegates__.shift
18
17
  attendant.uncast_object(self) if attendant.respond_to?(:uncast_object)
@@ -20,26 +19,26 @@ module Casting
20
19
  self
21
20
  end
22
21
 
23
- def delegated_methods(all=true)
24
- __delegates__.flat_map{|attendant|
22
+ def delegated_methods(all = true)
23
+ __delegates__.flat_map { |attendant|
25
24
  attendant_methods(attendant, all)
26
25
  }
27
26
  end
28
27
 
29
- def delegated_public_methods(include_super=true)
30
- __delegates__.flat_map{|attendant|
28
+ def delegated_public_methods(include_super = true)
29
+ __delegates__.flat_map { |attendant|
31
30
  attendant_public_methods(attendant, include_super)
32
31
  }
33
32
  end
34
33
 
35
- def delegated_protected_methods(include_super=true)
36
- __delegates__.flat_map{|attendant|
34
+ def delegated_protected_methods(include_super = true)
35
+ __delegates__.flat_map { |attendant|
37
36
  attendant_protected_methods(attendant, include_super)
38
37
  }
39
38
  end
40
39
 
41
- def delegated_private_methods(include_super=true)
42
- __delegates__.flat_map{|attendant|
40
+ def delegated_private_methods(include_super = true)
41
+ __delegates__.flat_map { |attendant|
43
42
  attendant_private_methods(attendant, include_super)
44
43
  }
45
44
  end
@@ -54,7 +53,7 @@ module Casting
54
53
 
55
54
  def method_missing(meth, ...)
56
55
  attendant = method_delegate(meth)
57
- if !!attendant
56
+ if attendant
58
57
  cast(meth, attendant, ...)
59
58
  else
60
59
  super
@@ -62,23 +61,23 @@ module Casting
62
61
  end
63
62
 
64
63
  def respond_to_missing?(meth, *)
65
- !!method_delegate(meth) || super
64
+ method_delegate(meth) ? true : super
66
65
  end
67
66
 
68
67
  def method_delegate(meth)
69
- __delegates__.find{|attendant|
68
+ __delegates__.find { |attendant|
70
69
  attendant.respond_to?(:method_defined?) && attendant.method_defined?(meth) ||
71
- attendant_methods(attendant).include?(meth)
70
+ attendant_methods(attendant).include?(meth)
72
71
  }
73
72
  end
74
73
 
75
- def attendant_methods(attendant, all=true)
74
+ def attendant_methods(attendant, all = true)
76
75
  collection = attendant_public_methods(attendant) + attendant_protected_methods(attendant)
77
76
  collection += attendant_private_methods(attendant) if all
78
77
  collection
79
78
  end
80
79
 
81
- def attendant_public_methods(attendant, include_super=true)
80
+ def attendant_public_methods(attendant, include_super = true)
82
81
  if Module === attendant
83
82
  attendant.public_instance_methods(include_super)
84
83
  else
@@ -86,7 +85,7 @@ module Casting
86
85
  end
87
86
  end
88
87
 
89
- def attendant_protected_methods(attendant, include_super=true)
88
+ def attendant_protected_methods(attendant, include_super = true)
90
89
  if Module === attendant
91
90
  attendant.protected_instance_methods(include_super)
92
91
  else
@@ -94,7 +93,7 @@ module Casting
94
93
  end
95
94
  end
96
95
 
97
- def attendant_private_methods(attendant, include_super=true)
96
+ def attendant_private_methods(attendant, include_super = true)
98
97
  if Module === attendant
99
98
  attendant.private_instance_methods(include_super)
100
99
  else
@@ -1,6 +1,5 @@
1
1
  module Casting
2
2
  module MissingMethodClientClass
3
-
4
3
  def self.extended(base)
5
4
  base.send(:include, InstanceMethods)
6
5
  end
@@ -26,7 +25,7 @@ module Casting
26
25
  end
27
26
 
28
27
  def method_class_delegate(meth)
29
- __class_delegates__.find{|attendant|
28
+ __class_delegates__.find { |attendant|
30
29
  attendant.method_defined?(meth)
31
30
  }
32
31
  end
@@ -44,7 +43,7 @@ module Casting
44
43
 
45
44
  def __delegates__
46
45
  Thread.current[:class_delegates] ||= {}
47
- Thread.current[:class_delegates][self.name] ||= []
46
+ Thread.current[:class_delegates][name] ||= []
48
47
  end
49
48
  end
50
- end
49
+ end
data/lib/casting/null.rb CHANGED
@@ -3,22 +3,28 @@ module Casting
3
3
  def self.instance_method(*_)
4
4
  Empty.instance_method(:null)
5
5
  end
6
+
6
7
  def self.method_defined?(*_)
7
8
  true
8
9
  end
9
10
  end
11
+
10
12
  module Blank
11
13
  def self.instance_method(*_)
12
14
  Empty.instance_method(:blank)
13
15
  end
16
+
14
17
  def self.method_defined?(*_)
15
18
  true
16
19
  end
17
20
  end
21
+
18
22
  module Empty
19
- def null(*, &_block); end
23
+ def null(*, &_block)
24
+ end
25
+
20
26
  def blank(*, &_block)
21
27
  ""
22
28
  end
23
- end
29
+ end
24
30
  end
@@ -1,6 +1,13 @@
1
1
  module Casting
2
2
  module SuperDelegate
3
-
3
+ # Cache regex matchers at module level for better performance
4
+ @casting_library_matcher = nil
5
+ @gem_home_matcher = nil
6
+ @debugging_matcher = /internal:trace_point/
7
+
8
+ class << self
9
+ attr_accessor :casting_library_matcher, :gem_home_matcher, :debugging_matcher
10
+ end
4
11
  # Call the method of the same name defined in the next delegate stored in your object
5
12
  #
6
13
  # Because Casting creates an alternative method lookup path using a collection of delegates,
@@ -19,7 +26,7 @@ module Casting
19
26
  #
20
27
  # module FormalGreeter
21
28
  # include Casting::Super
22
- #
29
+ #
23
30
  # def greet
24
31
  # "#{super_delegate}, how do you do?"
25
32
  # end
@@ -29,46 +36,63 @@ module Casting
29
36
  # some_object.greet #=> 'Hello, how do you do?'
30
37
  #
31
38
  def super_delegate(mod = :none, *args, **kwargs, &block)
32
- method_name = name_of_calling_method(caller_locations)
39
+ method_name, method_owner = name_and_owner_of_calling_method(caller_locations)
33
40
  owner = (mod unless mod == :none) || method_delegate(method_name)
34
41
 
35
42
  super_delegate_method = unbound_method_from_next_delegate(method_name, owner)
36
- super_delegate_method.bind(self).call(*args, **kwargs, &block)
43
+ super_delegate_method.bind_call(self, *args, **kwargs, &block)
37
44
  rescue NameError
38
- raise NoMethodError.new("super_delegate: no delegate method `#{method_name}' for #{self.inspect} from #{owner}")
45
+ # Use the method_owner from the call stack for consistent error messages
46
+ owner_name = method_owner || owner
47
+ raise NoMethodError.new("super_delegate: no delegate method `#{owner_name}##{method_name}' for #{inspect} from ")
39
48
  end
40
-
49
+
41
50
  def unbound_method_from_next_delegate(method_name, *skipped)
42
51
  method_delegate_skipping(method_name, *skipped).instance_method(method_name)
43
52
  end
44
-
53
+
45
54
  def method_delegate_skipping(meth, skipped)
46
55
  skipped_index = __delegates__.index(skipped)
47
- __delegates__[(skipped_index + 1)..__delegates__.length].find{|attendant|
56
+ __delegates__[(skipped_index + 1)..__delegates__.length].find { |attendant|
48
57
  attendant_methods(attendant).include?(meth)
49
58
  }
50
59
  end
51
60
 
52
61
  def calling_location(call_stack)
53
- call_stack.reject{|line|
62
+ call_stack.reject { |line|
54
63
  line.to_s.match? Regexp.union(casting_library_matcher, gem_home_matcher, debugging_matcher)
55
64
  }.first
56
65
  end
57
66
 
58
67
  def name_of_calling_method(call_stack)
59
- calling_location(call_stack).label.to_sym
68
+ method_name, _owner = name_and_owner_of_calling_method(call_stack)
69
+ method_name
70
+ end
71
+
72
+ def name_and_owner_of_calling_method(call_stack)
73
+ label = calling_location(call_stack).label
74
+ # Ruby 3.4.7+ includes module name in label (e.g., "ModuleName#method_name")
75
+ # Ruby 3.3 and earlier just has method name
76
+ parts = label.split("#")
77
+ if parts.length > 1
78
+ # Ruby 3.4.7+: has owner prefix
79
+ [parts.last.to_sym, parts.first]
80
+ else
81
+ # Ruby 3.3 and earlier: no owner prefix
82
+ [parts.first.to_sym, nil]
83
+ end
60
84
  end
61
-
85
+
62
86
  def casting_library_matcher
63
- Regexp.new(Dir.pwd.to_s + '/lib')
87
+ SuperDelegate.casting_library_matcher ||= Regexp.new(Dir.pwd.to_s + "/lib")
64
88
  end
65
89
 
66
90
  def gem_home_matcher
67
- Regexp.new(ENV['GEM_HOME'])
91
+ SuperDelegate.gem_home_matcher ||= Regexp.new(ENV["GEM_HOME"])
68
92
  end
69
93
 
70
94
  def debugging_matcher
71
- Regexp.new('internal:trace_point')
95
+ SuperDelegate.debugging_matcher
72
96
  end
73
97
  end
74
98
  end
@@ -1,3 +1,3 @@
1
1
  module Casting
2
- VERSION = '1.0.1'
2
+ VERSION = "1.0.3"
3
3
  end