Path: csiph.com!x330-a1.tempe.blueboxinc.net!feeder1.hal-mli.net!weretis.net!feeder4.news.weretis.net!feeds.phibee-telecom.net!talisker.lacave.net!lacave.net!not-for-mail From: 7stud -- Newsgroups: comp.lang.ruby Subject: Re: What do you do when you need to attach data to an object instance? Date: Thu, 14 Apr 2011 18:15:08 -0500 Organization: Service de news de lacave.net Lines: 76 Message-ID: <24ba002d74b2765157d36054768e8e73@ruby-forum.com> References: NNTP-Posting-Host: bristol.highgroove.com Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 7bit X-Trace: talisker.lacave.net 1302822950 2581 65.111.164.187 (14 Apr 2011 23:15:50 GMT) X-Complaints-To: abuse@lacave.net NNTP-Posting-Date: Thu, 14 Apr 2011 23:15:50 +0000 (UTC) In-Reply-To: X-Received-From: This message has been automatically forwarded from the ruby-talk mailing list by a gateway at comp.lang.ruby. If it is SPAM, it did not originate at comp.lang.ruby. Please report the original sender, and not us. Thanks! For more details about this gateway, please visit: http://blog.grayproductions.net/categories/the_gateway X-Mail-Count: 381578 X-Ml-Name: ruby-talk X-Rubymirror: Yes X-Ruby-Talk: <24ba002d74b2765157d36054768e8e73@ruby-forum.com> Xref: x330-a1.tempe.blueboxinc.net comp.lang.ruby:2891 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/.