What do you do when you see a need to be able to attach some data to
an object instance for later use somewhere else in a body of code?
Lately I’ve resorted to this:
Generic utility to allow one to attach data with a getter/setter to
any instance of any object so long as there isn’t a method name
collision:
def attach_data(obj, name, data)
getter = name.to_sym
setter = (name.to_s + ‘=’).to_sym
raise “method name collision for #{obj.class} instance” if
obj.respond_to?(getter) || obj.respond_to?(setter)
The ‘value’ local variable will remain in existence in the lambda
closures below:
value = data
meta = class << obj ; self ; end
meta.send(:define_method, getter, lambda { value }) ##
Getter closure
meta.send(:define_method, setter, lambda {|val| value = val }) ##
Setter closure
value
end
For example, in an application using SSH keys, I didn’t want to create
a new subclass, nor use an array or hash container instance just to
carry an OpenSSL::PKey::RSA object instance around the code. But I
needed to associate a user ID (user@host) to a key so it could be
accessed somewhere else. I figured it was easiest to just attach it
to the OpenSSL::PKey::RSA instance (see code above) directly. That
made the code cleaner, portions that only required the RSA key
directly, yet still gave the benefit of the key instance containing
the additional meta data I required.
What do you do when you need stuff like that? Monkey patch? Use a
container and pass it around instead? Or?
Is there a module version of OpenStruct that one can just include in
whatever class one wants to attach additional arbitrary data to? So I
could have done this instead:
require ‘ostructmod’
class OpenSSL::PKey
include OpenStructModule
end
???
Aaron out.