From: mortee Date: 2007-10-12T08:59:41+09:00 Subject: Re: Using strings to drill down into objects Ross X Dawson wrote: > Sorry folks the example was not correct > > irb(main):001:0> drill_down = lambda do |obj, method_names| > irb(main):002:1* o ||= obj > irb(main):003:1> method_names.split('.').each {|m| o = o.send(m)} > irb(main):004:1> o > irb(main):005:1> end > => # > irb(main):006:0> drill_down.call(1,'succ.to_s') > => "2" > irb(main):007:0> drill_down.call(1,'succ.succ.succ.to_s') > => "4" > irb(main):008:0> > > This is what I currently have working. I'm using it to define the columns > in a report so I need to determine the result of arbitrary fields within > the object model. I just look at the code and think there is a better way. OK, that makes more sense. Still, we don't know what you have to start with (I guess it's not simply 1 :), and how much flexibility you need in accessing various things about that thing. For example, do you really need a lambda as your "drill down" function? One might think if it's so flexible, a simple method would suffice. Also, are you sure you have to traverse an object hierarchy by following arbitrarily specifiable attribute accessors in turn? It seems quite weird for a data model. Finally, given that you already use lambdas, you could just use those to specify the way to access what you're looking for, starting from a given object. Just to keep some resemblance to your code (it could be made even simpler): def drill_down(obj, func) yield.call(obj) end drill_down(1, lambda{|o| o.succ.to_s}) #=> "2" drill_down(1, lambda{|o| o.succ.succ.succ.to_s}) #=> "4" And then you can simply use code blocks passed to the method call: def drill_down(obj) yield obj end drill_down(1) {|o| o.succ.to_s} #=> "2" drill_down(1) {|o| o.succ.succ.succ.to_s} #=> "4" If the method which calls drill_down receives the lambdas in question as parameters, you can still pass them on as code blocks: some_lambda = lambda{|o| o.succ.to_s} drill_down(1, &some_lambda) #=> "2" mortee