From: Ryan Davis Date: 2009-07-07T03:22:24+09:00 Subject: Re: A define_method question On Jul 6, 2009, at 09:11 , Juston wrote: > I have a question about define_method, more specifically how to bend > it to my purpose. > > The problem I am trying to solve is I have an object "Action" which > basically carries out a static set of actions based off instance > variables. "Action" can also be modified by MANY "Modifier"s. A > "Modifier" just adds in a little bit of extra code that can changes an > "Action"s operations just a bit. (Example: Action with a Modifier to > email someone with a report, something I wouldn't want on every object > and don't want to lump into some sort if/else statement in Action) > > What I would like to be able to do is have an empty method > "Action.runModifiedCode" within the "Action" class that would allow me > to just inject the code right into "Action." This is easy enough to do > using define_method (or a mix-in) to override the mock method, but > this doesn't work when the "Action" has more than one "Modifier." > > Long winded story short, is there something that would allow me to > take the code from one object method and append to another object's > method? in almost all cases I'm prolly going to suggest using eval instead of define method. I'm biased towards it, and so is ruby (there is a (very) slight speed penalty calling a method created with define_method). if simply calling them is sufficient (ie, they're not relying on manipulating local variables) then you can do something like: eval "def #{name}; #{features.compact.join("; "); end" If you truly need their bodies injected and find composing them as methods easier, then you may want to check out using a combination of ParseTree (1.8 only) and ruby2ruby. There are drawbacks there tho. First off, to get live extraction of method bodies, you have to use ParseTree or jump through extra hoops with ruby_parser. Either way it is pretty heavy handed but a very versatile option. Otherwise, some sort of in-between would be: feature_bodies = { :feature1 => "...code...", :feature2 => "...code...", ... } eval "def #{name}; #{features.compact.map { |n| feature_bodies[n] }.join("; "); end"