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 yield
ing 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
How to Overwrite a Printed Line in the Shell with Ruby
How to Write Rake Task to Import Data to Rails App
Why Do I Get an Error Installing the JSON Gem in Ubuntu
Ruby Gets/Puts Only for Strings
How to Insert a String into a Textfile
Converting a Hexadecimal Digest to Base64 in Ruby
Difference Between Downcase and Downcase! in Ruby
How Is a Local Variable Created Even When If Condition Evaluates to False in Ruby
Use Rvm to Force Specific Ruby in Xcode Run Script Build Phase
How to Run Only Specific Tests in Rspec
How to Add to a Serialized Array
How to Format This International Phone Number in Rails
How to Traverse Symlinked Directories in Ruby with a "**" Glob
Ruby Block to String Instead of Executing
Is There a Cucumber Hook to Run Before and After Each Feature