From: Rick DeNatale Date: 2009-04-27T04:55:29+09:00 Subject: Re: Using method missing to create getters and setters On Sun, Apr 26, 2009 at 3:30 PM, Robert Klemme wrote: > On 26.04.2009 19:40, Tim Conner wrote: >> My code currently looks like this: >> class BatchExternalBooking >>  def method_missing(method_sym, *args) >>    if method_sym.to_s =~ /^message_thread_([0-9]*)=?(\w*)?$/ >>      BatchExternalBooking.instance_eval "attr_accessor >> :message_thread_#{$1}" > > You might rather want to use class_eval here. No instance_eval works just as well for sending attr_accessor to a class/module. The only difference with class_eval is when using def to define a method. Both do the evaluation in the context of the receive but class_eval sets the current class to the receiver. Class.class_eval("def foo;end") defines an instance method while Class.instance_eval("def foo;end") defines a class method. This seems a bit less odd when you consider that a class method is just a singleton method on the class (albeit one which can be inherited by subclasses). > > Also, as Robert pointed out already, using $1 only once and storing the > value in a local variable is safer because it can be changed by any method > you invoke. > >>      self.send("message_thread_#{$1}=", $2) That's not true either. The $n variables are frame local, in a given invocation frame they will only change when another regex match is done in the same invocation. The bug here is that this line should have been self.send("message_thread_#{$1}=", *args) # or args.first if you must. Since the regexp only had a single capture, $2 is always nil, so even though the newly created setter is geting called, it's setting the instance variable to nil. -- Rick DeNatale Blog: http://talklikeaduck.denhaven2.com/ Twitter: http://twitter.com/RickDeNatale WWR: http://www.workingwithrails.com/person/9021-rick-denatale LinkedIn: http://www.linkedin.com/in/rickdenatale