From: Sharon Phillips Date: 2007-11-30T08:45:16+09:00 Subject: Re: define_method and instance variable maddness > 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 Funnily enough, that's how I'd done this originally, including calling my code variable 'code', using 'CODE' as the terminator and printing it to screen for debugging. I changed because I thought I was doing it the wrong way, and that the 'proper' way to do this sort of this was to use define_method. However... I really like Garry Wright's suggestion of using a hash to manage these lists. Much neater design than mine. Thanks for the suggestions. Cheers, Dave On 29/11/2007, at 3:22 AM, ara.t.howard wrote: > > 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 > > > >