From: "ara.t.howard" Date: 2007-11-29T01:22:28+09:00 Subject: Re: define_method and instance variable maddness On Nov 28, 2007, at 2:28 AM, Sharon Phillips wrote: > Here's the code snippet in question. It works, but is extremely > ugly with its constant usage of instance_variable_get and set. > > child_list_name= ('@'+(child.to_s)+"_list") > self_method= (self.name.downcase+'=').to_sym > method_name= ('add_'+child.to_s).to_sym > > define_method method_name do |new_child| > instance_variable_set(child_list_name, []) if > instance_variable_get(child_list_name).nil? > unless instance_variable_get(child_list_name).include? new_child > instance_variable_set(child_list_name, (instance_variable_get > (child_list_name) << new_child)) > if new_child.respond_to? self_method > new_child.send self_method, self > end > end > end > > > This is what I'd really like the new method to look like (for > child== :personnel): > > def add_personnel (new_personnel) > unless (@personnel_list||=[]).include? new_personnel > @personnel_list << new_personnel > self_method= (self.name.downcase+'=').to_sym > if new_personnel.respond_to? self_method > new_personnel.send self_method, self > end > end > end > > > Any help appreciated. eval strings, it's faster to debug by light years since you can dump it out to the screen. it also lets you use blocks. the cool kids use 'define_method', but then their methods cease to take blocks, enclose scope which cannot be freed, and are a pain in the butt to debug. starting with your sample method, which is the best way to start of course, i'd do cfp:~ > cat a.rb module Adder def attr_adder *names names.each do |name| code = <<-code def add_#{ name } (new_#{ name }) unless (@#{ name }||=[]).include? new_#{ name } @#{ name } << new_#{ name } self_method= (self.name.downcase+'=').to_sym if new_#{ name }.respond_to? self_method new_#{ name }.send self_method, self end end end code puts code if $DEBUG module_eval code end end def self.included other other.extend self end end class C include Adder attr_adder :personnel, :foobar end obviously writing this is quite easy: just start with your template and do some string substitution ;-) being able to dump the code out is HUGE when it comes to metaprogramming. i've even had libs that dumped it out so it could be, gasp, rdoc'd. define_method is quite useful at times, but i'd say this isn't it. kind regards. a @ http://codeforpeople.com/ -- it is not enough to be compassionate. you must act. h.h. the 14th dalai lama