From: 7stud -- Date: 2011-04-15T08:15:08+09:00 Subject: Re: What do you do when you need to attach data to an object instance? Aaron D. Gifford wrote in post #992841: > 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? > How about a decorator pattern? > 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. class SSL def talk puts 'hi' end end class MyWrapper def initialize(ssl_obj, key) @ssl_obj = ssl_obj @key = key end attr_accessor :ssl_obj, :key def method_missing(name, *args) @ssl_obj.send(name, *args) end end -- Posted via http://www.ruby-forum.com/.