casting 1.0.2 → 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: 2d5d851d5d006809d4704472259cd76692d864a6a2ddfc6ae829cfd65c15fe45
4
- data.tar.gz: 14e30f699b3cf4a7b488a18f013bd843ee5bcbc8e6d00595205fef5ae0d77a05
3
+ metadata.gz: 3e9ce2a6479f584071216d9aa62c7f076525325295cbd4df491dd6cbf4ffad39
4
+ data.tar.gz: 3c1475f0c68d62ac2ba37c542b5c7d0a8c6fddad91a88a7097c03dcdaa02f5d9
5
5
  SHA512:
6
- metadata.gz: 11e74b4ff72316f9bf5ee307b6f4f00603f09263127f59b8a53c22bb30d91b24f6e8bed3e60113b7e22da5903024a86acc170650d665e46e2cb7e0f5fad4b518
7
- data.tar.gz: c8d5513c9d70e879be06fc440f345b709a0ba84be8daaa941b3f034e9c1f21aa6aa614b87a24aa30e52cb0147c334adf497afef661ecaf7867df4009782b1b2d
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
data/Rakefile CHANGED
@@ -9,4 +9,11 @@ Rake::TestTask.new do |t|
9
9
  t.verbose = true
10
10
  end
11
11
 
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
+
12
19
  task default: :test
@@ -98,7 +98,8 @@ module Casting
98
98
  # Get the behavior module for the named role.
99
99
  # This role constant for special_person is SpecialPerson.
100
100
  def role_for(name)
101
- 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
102
103
  self.class.const_get(role_name)
103
104
  rescue NameError
104
105
  Module.new
@@ -53,7 +53,7 @@ module Casting
53
53
 
54
54
  def method_missing(meth, ...)
55
55
  attendant = method_delegate(meth)
56
- if !!attendant
56
+ if attendant
57
57
  cast(meth, attendant, ...)
58
58
  else
59
59
  super
@@ -61,7 +61,7 @@ module Casting
61
61
  end
62
62
 
63
63
  def respond_to_missing?(meth, *)
64
- !!method_delegate(meth) || super
64
+ method_delegate(meth) ? true : super
65
65
  end
66
66
 
67
67
  def method_delegate(meth)
@@ -1,5 +1,13 @@
1
1
  module Casting
2
2
  module SuperDelegate
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
3
11
  # Call the method of the same name defined in the next delegate stored in your object
4
12
  #
5
13
  # Because Casting creates an alternative method lookup path using a collection of delegates,
@@ -28,13 +36,15 @@ module Casting
28
36
  # some_object.greet #=> 'Hello, how do you do?'
29
37
  #
30
38
  def super_delegate(mod = :none, *args, **kwargs, &block)
31
- method_name = name_of_calling_method(caller_locations)
39
+ method_name, method_owner = name_and_owner_of_calling_method(caller_locations)
32
40
  owner = (mod unless mod == :none) || method_delegate(method_name)
33
41
 
34
42
  super_delegate_method = unbound_method_from_next_delegate(method_name, owner)
35
43
  super_delegate_method.bind_call(self, *args, **kwargs, &block)
36
44
  rescue NameError
37
- raise NoMethodError.new("super_delegate: no delegate method `#{method_name}' for #{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 ")
38
48
  end
39
49
 
40
50
  def unbound_method_from_next_delegate(method_name, *skipped)
@@ -55,19 +65,34 @@ module Casting
55
65
  end
56
66
 
57
67
  def name_of_calling_method(call_stack)
58
- 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
59
84
  end
60
85
 
61
86
  def casting_library_matcher
62
- Regexp.new(Dir.pwd.to_s + "/lib")
87
+ SuperDelegate.casting_library_matcher ||= Regexp.new(Dir.pwd.to_s + "/lib")
63
88
  end
64
89
 
65
90
  def gem_home_matcher
66
- Regexp.new(ENV["GEM_HOME"])
91
+ SuperDelegate.gem_home_matcher ||= Regexp.new(ENV["GEM_HOME"])
67
92
  end
68
93
 
69
94
  def debugging_matcher
70
- Regexp.new("internal:trace_point")
95
+ SuperDelegate.debugging_matcher
71
96
  end
72
97
  end
73
98
  end
@@ -1,3 +1,3 @@
1
1
  module Casting
2
- VERSION = "1.0.2"
2
+ VERSION = "1.0.3"
3
3
  end
metadata CHANGED
@@ -1,14 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: casting
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.2
4
+ version: 1.0.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jim Gay
8
- autorequire:
9
8
  bindir: bin
10
9
  cert_chain: []
11
- date: 2023-01-07 00:00:00.000000000 Z
10
+ date: 1980-01-02 00:00:00.000000000 Z
12
11
  dependencies: []
13
12
  description: |-
14
13
  Casting assists in method delegation which preserves the binding of 'self' to the object receiving a message.
@@ -38,7 +37,6 @@ homepage: http://github.com/saturnflyer/casting
38
37
  licenses:
39
38
  - MIT
40
39
  metadata: {}
41
- post_install_message:
42
40
  rdoc_options: []
43
41
  require_paths:
44
42
  - lib
@@ -53,8 +51,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
53
51
  - !ruby/object:Gem::Version
54
52
  version: '0'
55
53
  requirements: []
56
- rubygems_version: 3.2.27
57
- signing_key:
54
+ rubygems_version: 3.7.2
58
55
  specification_version: 4
59
56
  summary: Proper method delegation.
60
57
  test_files: []