Skip to content

Instantly share code, notes, and snippets.

@limhoff-r7
Created September 20, 2013 21:30
Show Gist options
  • Save limhoff-r7/6644221 to your computer and use it in GitHub Desktop.
Save limhoff-r7/6644221 to your computer and use it in GitHub Desktop.
Use WeakRef to allow ActiveRecords to be collected, but allow the ActiveRecord to be recreated when needed. Allows a module, class, or instance to keep track of its own metadata without constantly having the metadata in memory and allowing the metadata to be reused without needing pass it through all the cache construction.
resurrecting_attr_accessor :module_ancestor do
ActiveRecord::Base.connection_pool.with_connection do
Mdm::Module::Ancestor.where(real_path_sha1_hex_digest: real_path_sha1_hex_digest).first
end
end
module Metasploit::Framework::ResurrectingAttribute
def resurrecting_attr_accessor(attribute_name, &block)
instance_variable_name = "@#{attribute_name}".to_sym
getter_name = attribute_name
setter_name = "#{attribute_name}="
define_method(getter_name) do
begin
strong_reference = nil
weak_reference = instance_variable_get instance_variable_name
if weak_reference
strong_reference = weak_reference.__getobj__
else
strong_reference = instance_exec(&block)
send(setter_name, strong_reference)
end
rescue WeakRef::RefError
# try again by rebuild because __getobj__ failed on the weak_reference because the referenced object was garbage
# collected.
instance_variable_set instance_variable_name, nil
retry
end
# Return strong reference so consuming code doesn't have to handle the weak_reference being garbase collected.
strong_reference
end
define_method(setter_name) do |strong_reference|
weak_reference = WeakRef.new(strong_reference)
instance_variable_set instance_variable_name, weak_reference
end
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment