Ruby Block to String Instead of Executing

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.

Ruby - when is block executed?


I didn't write - foo() stuff like that.

In Ruby, parentheses are optional when calling methods. You can call a method without parentheses. For example, puts is often called without parentheses like this:

puts "hello"

You are calling your method here:

my_block = foo { puts "hello" }
# ^^^

So my assumption is..
When you declare block, It implicitly means that it will execute the method with the same name of the block

It is unclear what you are asking here. A block doesn't have a name, so "the method with the same name of the block" doesn't make sense. A block is a special argument to a method call. It cannot appear anywhere else except as the last argument of a method call. It cannot be assigned to a variable, it cannot be returned from a method, it cannot be given a name. It is not an object or a value.

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.

How can I use a block to change the execution context in ruby?

It looks like you are sending methods to a class/module, so your example may be simply rewritten with use of Module#class_eval method:

name { Faker::Hacker.class_eval { "#{ingverb} #{adjective} #{noun}" } }

would invoke methods in the block passed to class_eval on Faker::Hacker class.

Implement to_s(2) with String#to_proc in Ruby

When you run some_method(&some_obj), Ruby first call the some_obj.to_proc to get a proc, then it "converts" that proc to a block and passes that block to some_method. So how the arguments go into the proc depends on how some_method passes arguments to the block.

For example, as you defined String#to_proc, which returns a proc{|arg| ...} (a proc with one argument), and calls [...].map(&'to_s 2'), Ruby interprets it as

[...].map(&('to_s 2'.to_proc))

which is

[...].map(&proc{|arg| ... })

and finally

[...].map {|arg| ... }

How does Ruby's block syntax work?

Let's first forget about Active Record and focus on the code structure itself. Here is a super simple version of that structure.

class MyBuilder
def initialize
# keys are property names, values are options
@properties = {}
end

def property(name, options={})
@properties[name] = options
end

def build
# For simplicity, just return all properties
@properties
end
end

def create_thing(name)
puts "Begin creating #{name}"

builder = MyBuilder.new

puts "Let user use the builder to define properties"
yield builder

puts "Consume the builder"
properties = builder.build

puts "Persist changes to #{name}..."
# For simplicity just print them out
p properties

puts 'done'
end

create_thing :bar do |builder|
builder.property :counter, color: 'brown'
builder.property :wine_storage, texture: 'wood'
end

Please type the code above by hand to grab some feel.

Although the code above has nothing to do with Active Record, it has the same structure as the migration.

When ever create_table is called, it instantiates a builder (of type TableDefinition), and "pushes" that builder to the block (by yielding it) in order to let user define the tables columns. The builder is consumed later by create_table when the user is done defining the columns.

How to use a Ruby block to assign variables in chef recipe

Your problem is compile time versus converge time. Your block will be run at converge time but at this time the node['host'] in the execute resource has already been evaluated.

The best solution in this case would be to use lazy evaluation so the variable will be expanded when the resource is converged instead of when it is compiled:

execute "Enable on hosts" do
command lazy { "#{path}/command --enable -N #{node['hosts']}" }
end

Here's a little warning though, the lazy operator has to include the full command attribute text and not only the variable, it can work only as first keyword after the attribute name.



Related Topics



Leave a reply



Submit