9

Let's say I have a proc/lambda/block/method/etc like so:

2.1.2 :075 > procedure = Proc.new { |a, b=2, *c, &d| 42 }
 => #<Proc:0x000000031fcd10@(irb):75> 

I know I can find out the names of the parameters with:

2.1.2 :080 > procedure.parameters
 => [[:opt, :a], [:opt, :b], [:rest, :c], [:block, :d]]

But how do I go about getting the value that a given optional parameter would assume if it is not given?


PS: Yes. I know this has been asked/answered before here, but the previous solution requires the use of the merb gem, which is actually slightly misleading. merb itself depended on the methopara gem (unless you're on JRuby or MRI, which I am not) which itself provided the feature at the time the question was answered.

Sadly, presently, methopara appears to be abandonware. Also, it only ever supported ruby 1.9 (and not even the latest version thereof), so I'm looking for a solution that works for current ruby versions.

Community
  • 1
  • 1
mikev
  • 111
  • 1
  • 3
  • 2
    I think this is nearly impossible, you must take in account that the so called `default` value can be any kind of executable code and it will be executed every time you call it. – hahcho Jan 06 '15 at 11:56
  • @hakcho, very good catch. (I totally lost track of this account and used an entirely different approach since I posted this.) Still, it would be nice to have programmatic access to that value (or routine, if it is one). – mikev Mar 05 '16 at 22:42

1 Answers1

2

Assuming the proc / lambda was defined in a file, you can use the source_location method to find the location of that file and the line number it was defined on.

2.2.0 (main):0 > OH_MY_PROC.source_location
=> [
  [0] "sandbox/proc.rb",
  [1] 1
]

With some help from File.readlines we can make a short method that when passed a proc / lambda can spit out the source line it was defined on.

def view_def proc_lambda
  location = proc_lambda.source_location
  File.readlines(location[0])[location[1]-1]
end

In action it looks something like this

2.2.0 (main):0 > view_def OH_MY_PROC
=> "OH_MY_PROC = Proc.new { |a, b=2, *c, &d| 42 }\n"
2.2.0 (main):0 > view_def OH_MY_LAMBDA
=> "OH_MY_LAMBDA = ->(a, b=2, *c, &d) { 42 }\n"

If you want to do the same for methods it becomes a bit more involved. In that case I recommend reading this blog post from the Pragmatic Studio blog: "View Source" On Ruby Methods

brownmike
  • 1,714
  • 1
  • 11
  • 11
  • might as well use merb. source_location is great when you rescue an exception and want to open the proc in your text editor – Rivenfall Mar 07 '15 at 11:29
  • @rivenfall Please see original post. Merb is not an option due to an abandoned dependency. – mikev Mar 05 '16 at 22:39
  • @brownmike I had been looking for a way to do this without parsing source code on my own, but thanks for the idea. In any case I have since gone a different way. – mikev Mar 05 '16 at 22:45