Skip to content

Commit

Permalink
Use attached_object in ruby 3.2+.
Browse files Browse the repository at this point in the history
  • Loading branch information
alpaca-tc committed Sep 15, 2023
1 parent ed0fb3e commit 6c08225
Show file tree
Hide file tree
Showing 2 changed files with 37 additions and 12 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ _No breaking changes!_
- Updated `Dry::Core` gem version to 1.0.0 in benchmarks [[#297]](https://github.com/panorama-ed/memo_wise/pull/297)
- Updated `Memery` gem version to 1.5.0 in benchmarks [[#313]](https://github.com/panorama-ed/memo_wise/pull/313)
- Updated `Memoized` gem version to 1.1.1 in benchmarks [[#288]](https://github.com/panorama-ed/memo_wise/pull/288)
- In Ruby3.2+, for singleton classes, use `#attached_object` instead of `ObjectSpace` [[#318]](https://github.com/panorama-ed/memo_wise/pull/318)
- Reorganized `CHANGELOG.md` for improved clarity and completeness
[[#282](https://github.com/panorama-ed/memo_wise/pull/282)]

Expand Down
48 changes: 36 additions & 12 deletions lib/memo_wise/internal_api.rb
Original file line number Diff line number Diff line change
Expand Up @@ -126,18 +126,7 @@ def self.key_str(method)
def self.original_class_from_singleton(klass)
raise ArgumentError, "Must be a singleton class: #{klass.inspect}" unless klass.singleton_class?

# Since we call this method a lot, we memoize the results. This can have a
# huge impact; for example, in our test suite this drops our test times
# from over five minutes to just a few seconds.
@original_class_from_singleton ||= {}

# Search ObjectSpace
# * 1:1 relationship of singleton class to original class is documented
# * Performance concern: searches all Class objects
# But, only runs at load time and results are memoized
@original_class_from_singleton[klass] ||= ObjectSpace.each_object(Module).find do |cls|
cls.singleton_class == klass
end
find_attached_object(klass)
end

# Convention we use for renaming the original method when we replace with
Expand Down Expand Up @@ -208,5 +197,40 @@ def self.target_class(target)
end
end
private_class_method :target_class

if Module.singleton_class.respond_to?(:attached_object)
# In Ruby3.2+, for singleton classes, `#attached_object` returns the object this class is for
# https://bugs.ruby-lang.org/issues/12084
#
# @param klass [Class]
# Singleton class to find the original class of
#
# @return Class
# Original class for which `klass` is the singleton class.
def self.find_attached_object(klass)
klass.attached_object
end
else
# @param klass [Class]
# Singleton class to find the original class of
#
# @return Class
# Original class for which `klass` is the singleton class.
def self.find_attached_object(klass)
# Since we call this method a lot, we memoize the results. This can have a
# huge impact; for example, in our test suite this drops our test times
# from over five minutes to just a few seconds.
@original_class_from_singleton ||= {}

# Search ObjectSpace
# * 1:1 relationship of singleton class to original class is documented
# * Performance concern: searches all Class objects
# But, only runs at load time and results are memoized
@original_class_from_singleton[klass] ||= ObjectSpace.each_object(Module).find do |cls|
cls.singleton_class == klass
end
end
end
private_class_method :find_attached_object
end
end

0 comments on commit 6c08225

Please sign in to comment.