Ruby block to string instead of executing [duplicate] - ruby

This question already has answers here:
Printing the source code of a Ruby block
(6 answers)
Closed 8 years ago.
Take this example:
write_as_string { puts 'x' }
I then want to be able to do
def write_as_string(&block)
puts block.to_s
end
When I execute this, I want the output to be:
"puts 'x'"
I want to be able to receive the block and get the actual code for the block instead of executing it.
Motivation: Creating a DSL, I want to the mock to be converted into a number of other method calls, hidden from the calling code - using existing objects and methods without monkey patching them.
Any ideas on this would be great!
Thanks
Ben

If you're on Ruby 1.9, you can use the sourcify gem. It provides Proc#to_source, which is like ParseTree's Proc#to_ruby.
When using sourcify, if you have nested procs in your source code, you might have to help it along with the :attached_to option:
## (Works in Ruby 1.8) Using ParseTree (with parse_tree_extensions)
block.to_ruby
## (Works in Ruby 1.9) Using sourcify
block.to_source
## Try this if you get Sourcify::NoMatchingProcError or Sourcify::MultipleMatchingProcsPerLineError
block.to_source :attached_to => :name_of_block_in_source_code
I posted about ParseTree and Ruby 1.9 in my company's blog.

Duplicate: Printing the source code of a Ruby block
sudo gem install ParseTree
sudo gem install ruby2ruby
then
require 'rubygems'
require 'parse_tree'
require 'parse_tree_extensions'
require 'ruby2ruby'
def block_as_string &block
block.to_ruby
end
results in
irb(main):008:0> block_as_string {puts 'x'}
=> "proc { puts(\"x\") }"

You want the ruby2ruby gem, which does this nicely. Unfortunately, to analyze a block this gem depends on ParseTree, which is unsupported in Ruby 1.9.

Related

Force .rb file running under specific ruby versions

I write a ruby script in a .rb file. It uses latest Ruby features (version 2.7). Is there any way to force this .rb file can only be executed in a specific Ruby version range? For example, the first line of a .rb file could be:
#! ruby 2.7+
# This .rb file can only be run with Ruby version 2.7 or above
Use the gem semantic to handle parsing the current Ruby version:
require 'semantic'
# Require >= 2.7 < 3
exit unless Semantic::Version.new(RUBY_VERSION).satisfies?('~> 2.7')
# Require >= 2.7, including 3 and above
exit unless Semantic::Version.new(RUBY_VERSION).satisfies?('>= 2.7')
This requires you to use bundler and a Gemfile with your app.
Other comparators are listed in the source code for the gem:
if ['<', '>', '<=', '>='].include?(comparator)
satisfies_comparator? comparator, pad_version_string(other_version_string)
elsif comparator == '~>'
pessimistic_match? other_version_string
else
tilde_matches? other_version_string
end
This will allow you to fine-tune your version requirements.
Naively,
unless RUBY_VERSION[0, 3] == "2.7"
puts "You need 2.7")
exit
end

How do I get method signatures or method descriptions in Ruby's irb? [duplicate]

This question already has answers here:
In ruby, is there a way to know in the console what a method does?
(2 answers)
Closed 3 years ago.
I'm wondering if Ruby's irb has the ability to supply method/function signatures or descriptions.
I know I can do something like this in the irb
[].methods.sort
and get all the methods/functions available to arrays but how can I get more information(while in the irb) about specific methods/functions?
You can use #method and then use Method methods:
1.method(:+).arity
# => 1
1.method(:+).parameters
# => [[:req]]
[].method(:reduce).parameters
# => [[:rest]]
This is new for me as I've commented on ruby 2.7 they will improve irb's documentation. here is the pull request on ruby core that to it.
If you read the pull request you are able to do this.
2.6.3 :003 > require 'rdoc'
=> true
2.6.3 :003 > driver = RDoc::RI::Driver.new
=> # here you will see all rdoc docs
2.6.3 :005 > driver.display_name("Bundler::CLI::Common")
Pretty Cool no?

Need to call different Ruby method depending on what version is installed

I have a Ruby script that iterates over each line of a text file.
In Ruby 1.8.* using content.each do |line| works fine, but in Ruby 1.9.* that does not work, and I need to use content.each_line do |line|.
Since this script will be used by several different people, I need to be able to use the right method depending on their version of Ruby.
Is there a way to do this?
The global constant RUBY_VERSION contains the version of the currently running Ruby. So this script will do what you want:
if RUBY_VERSION < "1.9.2"
# code for 1.8.7
else
# code for 1.9.2+
end
If the inner code of the each_line is equal with 1.8.* and 1.9.*, the following approach is more DRY:
each_selector = RUBY_VERSION < "1.9.2" ? :each : :each_line
content.send(each_selector) do | line|
# ...
end

Am I using the StanfordParser wrapper for ruby properly? It's returning incorrect results

I've installed the latest version of the stanfordparser and the ruby wrapper library for it. When trying to test it with a simple example from the website:
vi test.rb:
require "stanfordparser"
preproc =
StanfordParser::DocumentPreprocessor.new
puts
preproc.getSentencesFromString("This
is a sentence. So is this.")
ruby -rubygems test.rb
This
is
a
sentence
.
So
is
this
.
This is a sanity check really - am I doing something wrong, or is this a bug in the parser or wrapper?
You might be confused about how puts is formatting the output. Try this:
x = preproc.getSentencesFromString("This is a sentence. So is this.")
puts x.inspect
to make sure that you're getting what you're supposed to be getting.

Accessing info about rubygem from within ruby script

I need to get the installation path for a given ruby gem and can't find any information on how to do that. Given:
#!/usr/bin/env ruby
require 'rubygems'
require 'somegem'
How can I find out where the installation path of somegem is on the system (without resorting to system(gem ...). The gem in question comes with some icons which I want to reference in my script.
Thanks to Chris I now have the following assembled:
require 'rubygems/Commands/contents_command'
c = Gem::Commands::ContentsCommand.new
c.options[:args] = 'somegem'
c.execute
However, c.execute immediately outputs the result on stdout. How can I catch that in a variable for further processing? res = c.execute does not work.
You have different ways to achieve this:
Gem.source_index.find_name('somegem').last.full_gem_path
You could also just grep your load path:
$:.grep /somegem/

Resources