Printing the Source Code of a Ruby Block

Printing the source code of a Ruby block

You can do this with Ruby2Ruby which implements a to_ruby method.

require 'rubygems'
require 'parse_tree'
require 'parse_tree_extensions'
require 'ruby2ruby'

def meth &block
puts block.to_ruby
end

meth { some code }

will output:

"proc { some(code) }"

I would also check out this awesome talk by Chris Wanstrath of Github http://goruco2008.confreaks.com/03_wanstrath.html He shows some interesting ruby2ruby and parsetree usage examples.

Print the actual Ruby code of a block?

This question is related to:

  • Converting Proc and Method to String
  • How to extract the code from a Proc object?
  • Ruby block to string instead of executing
  • Compare the Content, Not the Results, of Procs

as Andrew suggested me when I asked the first one in this list. By using the gem 'sourcify', you can get something close to the block, but not exactly the same:

require 'sourcify'

def block_to_s(&blk)
blk.to_source(:strip_enclosure => true)
end

puts block_to_s {
str = "Hello"
str.reverse!
print str
}

In above, notice that you either have to put parentheses around the argument of puts (block_to_s ... end) or use {...} instead of do ... end because of the strength of connectivity as discussed repeatedly in stackoverflow.

This will give you:

str = "Hello"
str.reverse!
print(str)

which is equivalent to the original block as a ruby script, but not the exact same string.

Is it possible to see the ruby code in a proc?

Take a look at the sourcify gem:

proc { x + y }.to_source
# >> "proc { (x + y) }"

Can I access the source of a ruby block without &block?

So, the real issue here is that I didn't read all the Pry help (specifically rescue-pry) and didn't know about the up command...

Usage: up [OPTIONS]
Go up to the caller's context. Accepts optional numeric parameter for how many frames to move up.
Also accepts a string (regex) instead of numeric; for jumping to nearest parent method frame which matches the regex.
e.g: up #=> Move up 1 stack frame.
e.g: up 3 #=> Move up 2 stack frames.
e.g: up meth #=> Jump to nearest parent stack frame whose method matches /meth/ regex, i.e `my_method`.

-h, --help Show this message.

By executing up within a pry session from a raised exception, I was able to get to the block where the exception was raised and inspect the local variables I needed.

How can I get source code of a method dynamically and also which file is this method locate in

Use source_location:

class A
def foo
end
end

file, line = A.instance_method(:foo).source_location
# or
file, line = A.new.method(:foo).source_location
puts "Method foo is defined in #{file}, line #{line}"
# => "Method foo is defined in temp.rb, line 2"

Note that for builtin methods, source_location returns nil. If want to check out the C source code (have fun!), you'll have to look for the right C file (they're more or less organized by class) and find the rb_define_method for the method (towards the end of the file).

In Ruby 1.8 this method does not exist, but you can use this gem.

ruby block not executing code, only printing output

I would not recommend using ruby blocks this way, just add the recipes in the order you want Chef to execute them. In this case:

include_recipe 'sap-bowbridge::default'
include_recipe 'ids::bowbridge_config'

Now, if you need some values to be obtained during execution of the Chef-client, you can use a lazy evaluation. There is plenty of information in Chef website.

As an example, check this:

link '/lib64/libvsa.so' do
to lazy { find_file '/opt/bowbridge/libAVB*_mcaf.so' }
end

Finally, try to use simple quotes ' ' rather than double " " if there is no need for interpolation or adding variables to the text, also related to this, please use:

"/etc/bowbridge/#{bb_cfg}"

Rather than

"/etc/bowbridge/" + bb_cfg

ruby block/procs and method call

The block following your method call { |s| puts s } does nothing until you tell it to. If you continue reading the page they explain blocks further down - here is an example:

def accepts_hash( var )
print "got: ", var.inspect # will print out what it received
yield ' jenny from the block' # pass value back to block
end

accepts_hash( { :arg1 => 'giving arg1', :argN => 'giving argN' } ) { |s| puts s }

=> {:arg1=>"giving arg1", :argN=>"giving argN"} jenny from the block

By yielding, we can return and process the block - in this case s represents the string we are yielding, and ' jenny from the block' is its value.

Blocks make ruby more flexible and declarative, allowing you to write idiomatic and human readable code. For example:

3.times { p 'hello' } 
=> "hello"
=> "hello"
=> "hello"

ruby is a gorgeous lanuage - more info on blocks and practical usage: http://www.gotealeaf.com/blog/declarative-thinking-with-higher-order-functions-and-blocks



Related Topics



Leave a reply



Submit