IRB called from byebug loses context - ruby

When I call IRB from a byebug breakpoint I seem not to be in the expected context. Is this a bug or am I doing something incredibly stupid?
$ ruby -v
ruby 2.2.0p0 (2014-12-25 revision 49005) [x86_64-darwin14]
$ ruby test.rb
test
[3, 12] in test.rb
3:
4: def initialize
5: #a = "test"
6: puts #a
7: byebug
=> 8: puts #a
9: end
10: end
11:
12: Test.new
(byebug) irb
2.2.0 :001 > #a
=> nil
I'd expect #a to be "test", but it's undefined/nil.

It is a bug, you should open an issue in Byebug's issue tracker if you want it fixed or at least studied.

Don't call irb, you can use the byebug prompt in the same way as you'd use IRB.

Related

ruby error of "block in initialize: uninitialized constant" but running well with irb

I have a ruby script as following:
class HashSet < Hash
def initialize
super { |hash, key| hash[key] = Set.new }
end
end
data = {}
data["hash"] ||= HashSet.new
data["hash"]["colors"].add "blue"
puts data
An error is raised when run this script:
$ ruby demo.rb
Traceback (most recent call last):
2: from demo.rb:9:in `<main>'
1: from demo.rb:9:in `[]'
demo.rb:3:in `block in initialize': uninitialized constant HashSet::Set (NameError)
But when I run it with irb, it runs well:
$ irb -r ./demo.rb
{"hash"=>{"colors"=>#<Set: {"blue"}>}}
What makes the difference and how can I fix the script?
Add this to the top of your script:
require "set"
Explanation:
Set is not part of the ruby core library. Rather, it is part of the ruby standard library.
In order to use Set, you must - somewhere - require the library explicitly.
As it happens, irb actually already requires set as part of its initialisation process:
$ irb
irb(main):001:0> Set
=> Set
$ ruby -e 'Set'
Traceback (most recent call last):
-e:1:in `<main>': uninitialized constant Set (NameError)

Byebug does not update local variable on Ubuntu

Here's my code:
# please_just_work.rb
require 'bundler/setup'
Bundler.require
byebug
puts "a = #{a}"
Inside the byebug session I set the value of a, but it remains undefined:
[1, 5] in /home/paper/tmp/debug.rb
1: require 'bundler/setup'
2: Bundler.require
3:
4: byebug
=> 5: puts "a = #{a}"
(byebug) a = 1
1
(byebug) continue
Traceback (most recent call last):
please_just_work.rb:5:in `<main>': undefined local variable or method `a' for main:Object (NameError)
I'm running Ubuntu 18.04
Turns out I had to use #a instead of a. I did not find this in the documentation, so I'll leave the answer here for whoever faces this same issue.

Run unit test with Ruby 2.0 and minitest 5.5 without Gemfile

I was learning Ruby by reading Programming Ruby and there is this example code:
require_relative 'count_frequency'
require_relative 'words_from_string'
require 'test/unit'
class TestWordsFromString < Test::Unit::TestCase
def test_empty_string
assert_equal([], words_from_string(''))
assert_equal [], words_from_string(' ')
end
def test_single_word
assert_equal ['cat'], words_from_string('cat')
assert_equal ['cat'], words_from_string(' cat ')
end
def test_many_words
assert_equal ['the', 'cat', 'sat', 'on', 'the', 'cat'], words_from_string('the cat sat on the mat')
end
def test_ignore_punctuation
assert_equal ['the', "cat's", 'mat'], words_from_string("the cat's mat")
end
end
When I tried to run it, an error occured:
MiniTest::Unit::TestCase is now Minitest::Test.
More detailed error message:
I'm using ruby 2.0.0p481 (2014-05-08 revision 45883) [universal.x86_64-darwin14] and minitest (5.5.0, 5.4.3, 5.3.5, 4.3.2). I did some search and found that since minitest5.0, MiniTest::Unit::TestCase has changed to Minitest::Test. But I cannot do anything since it's in the source file of the gem. Some suggests that require minitest 4.** in Gemfile, but i'm just running a few scripts. There is no need for Gemfile I suppose. And I certainly don't want to uninstalling minitest5.**. So is there a way I could run this script with minitest5.5 and ruby 2.0?
The tests should still run. I have the same set up and even though I get that error, the tests are executed.
→ ruby --verbose etl_test.rb
MiniTest::Unit::TestCase is now Minitest::Test. From etl_test.rb:4:in `<main>'
Run options: --seed 61653
# Running:
....
Finished in 0.001316s, 3039.5137 runs/s, 3039.5137 assertions/s.
4 runs, 4 assertions, 0 failures, 0 errors, 0 skips
classyhacker:~/dev/github/exercism/ruby/etl
→ rbenv versions
system
1.9.3-p448
2.0.0-p451
2.1.0
2.1.1
2.1.2
* 2.1.3 (set by RBENV_VERSION environment variable)
jruby-1.7.8
classyhacker:~/dev/github/exercism/ruby/etl
→ gem list | grep minitest
minitest (5.5.1, 5.4.3, 4.7.5)
My test looks like
require 'minitest/autorun'
require_relative 'etl'
class TransformTest < MiniTest::Unit::TestCase
def test_transform_one_value
old = { 1 => ['A'] }
expected = { 'a' => 1 }
assert_equal expected, ETL.transform(old)
end
require minitest/autorun is also the suggested way in rubydoc http://ruby-doc.org/stdlib-2.0.0/libdoc/minitest/rdoc/MiniTest.html

LoadError on require './primes.rb' in terminal

When I do require './primes.rb' in irb I get this:
1.9.3-p392 :004 > require './primes.rb'
LoadError: cannot load such file -- ./primes.rb
from /Users/RBonhardt/.rvm/rubies/ruby-1.9.3-p392/lib/ruby/site_ruby/1.9.1/rubygems/custom_require.rb:36:in `require'
from /Users/RBonhardt/.rvm/rubies/ruby-1.9.3-p392/lib/ruby/site_ruby/1.9.1/rubygems/custom_require.rb:36:in `require'
from (irb):4
from /Users/RBonhardt/.rvm/rubies/ruby-1.9.3-p392/bin/irb:16:in `<main>'
Here is the primes.rb document:
# primes.rb
require 'debugger'
def prime?(num)
debugger
(1..num).each do |i|
if (num % i) == 0
return false
end
end
end
def primes(num_primes)
ps = []
num = 1
while ps.count < num_primes
primes << num if prime?(num)
end
end
if __FILE__ == $PROGRAM_NAME
puts primes(100)
end
Any suggestions of how to get this to work would be greatly appreciated!
When I do require relative it gives me this:
1.9.3-p392 :010 > require_relative 'primes.rb'
LoadError: cannot infer basepath
from (irb):10:in `require_relative'
from (irb):10
from /Users/RBonhardt/.rvm/rubies/ruby-1.9.3-p392/bin/irb:16:in `<main>'
When I do the second solution below it gives me this:
1.9.3-p392 :013 > $LOAD_PATH << "."
=> ["/Users/RBonhardt/.rvm/rubies/ruby-1.9.3-p392/lib/ruby/site_ruby/1.9.1", "/Users/RBonhardt/.rvm/rubies/ruby-1.9.3-p392/lib/ruby/site_ruby/1.9.1/x86_64-darwin11.4.2", "/Users/RBonhardt/.rvm/rubies/ruby-1.9.3-p392/lib/ruby/site_ruby", "/Users/RBonhardt/.rvm/rubies/ruby-1.9.3-p392/lib/ruby/vendor_ruby/1.9.1", "/Users/RBonhardt/.rvm/rubies/ruby-1.9.3-p392/lib/ruby/vendor_ruby/1.9.1/x86_64-darwin11.4.2", "/Users/RBonhardt/.rvm/rubies/ruby-1.9.3-p392/lib/ruby/vendor_ruby", "/Users/RBonhardt/.rvm/rubies/ruby-1.9.3-p392/lib/ruby/1.9.1", "/Users/RBonhardt/.rvm/rubies/ruby-1.9.3-p392/lib/ruby/1.9.1/x86_64-darwin11.4.2", "."]
1.9.3-p392 :014 > require 'primes.rb'
LoadError: cannot load such file -- primes.rb
from /Users/RBonhardt/.rvm/rubies/ruby-1.9.3-p392/lib/ruby/site_ruby/1.9.1/rubygems/custom_require.rb:36:in `require'
from /Users/RBonhardt/.rvm/rubies/ruby-1.9.3-p392/lib/ruby/site_ruby/1.9.1/rubygems/custom_require.rb:36:in `require'
from (irb):14
from /Users/RBonhardt/.rvm/rubies/ruby-1.9.3-p392/bin/irb:16:in `<main>'
1.9.3-p392 :015 >
When I try it in pry:
[4] pry(main)> require_relative 'primes.rb'
LoadError: cannot infer basepath
from (pry):2:in `require_relative'
[5] pry(main)> require 'primes.rb'
LoadError: cannot load such file -- primes.rb
from /Users/RBonhardt/.rvm/rubies/ruby-1.9.3-p392/lib/ruby/site_ruby/1.9.1/rubygems/custom_require.rb:36:in `require'
[6] pry(main)> .ls
Applications Movies git-completion.bash
Desktop Music rails_projects
Documents Pictures ruby
Downloads Public runwithfriends
Dropbox code shopify
Library dev sites
[7] pry(main)> require 'ruby/app_acad_mini_curriculum/debugging/primes.rb'
LoadError: cannot load such file -- ruby/app_acad_mini_curriculum/debugging/primes.rb
from /Users/RBonhardt/.rvm/rubies/ruby-1.9.3-p392/lib/ruby/site_ruby/1.9.1/rubygems/custom_require.rb:36:in `require'
Try require_relative
require_relative 'primes.rb'
EDIT:
Note that this will only work from within a script. If you are trying to require this script into an irb session then you will need to provide the full path to primes.rb. The reason is where irb's location is. For instance, try Dir.pwd inside irb and you will see where require_relative is attempting to search for primes.rb.
There are a couple things you could do:
# Just need to require the one file.
require_relative File.join('users', 'yourusername', 'prime_folder', 'prime.rb')
# Many files in the same folder
$LOAD_PATH << File.join('users', 'yourusername', 'prime_folder')
require 'prime.rb'
require 'another_file.rb'
Another option, one that I use, is Pry. It is like irb and is very easy to call from a script. It is a gem so:
gem install pry
At the end of your script, you could do:
if $0 == __FILE__
require 'pry'
binding.pry
end
You would then drop into an irb like REPL where you can test and debug your methods. I can't survive without it.
unlike ruby 1.8, you can't require a file that is in the same folder, because the current folder is not on the load path any longer.
To emulate the behavior of ruby 1.8, you could try
$LOAD_PATH << "."
require 'primes.rb'
However, the correct way to do in ruby 1.9, as #CharlesCaldwell pointed, is using relative_require.
Here is a good discussion of the best way to deal with this.
note that relative_require does not work in irb. You can check the motive on #CharlesCaldwell answer.
But looking in your task question, you should not use irb, you should use pry:
We're going to use two gems. One is called Pry, which is a replacement for irb. You'll have to gem install pry. It's not essential for debugging that you use Pry, but it will make life nicer.
Here is an example using relative require:
[fotanus#thing ~]$ cat primes.rb
# primes.rb
def prime?(num)
(1..num).each do |i|
if (num % i) == 0
return false
end
end
end
def primes(num_primes)
ps = []
num = 1
while ps.count < num_primes
primes << num if prime?(num)
end
end
if __FILE__ == $PROGRAM_NAME
puts primes(100)
end
[fotanus#thing ~]$ cat a.rb
require_relative 'primes.rb'
[fotanus#thing ~]$ ruby a.rb

Why do I get "stack level too deep" from method_missing in irb 1.9.3?

Scenario:
-bash-3.2$ irb -f
ruby-1.9.3-p0 :001 > #v = {}
=> {}
ruby-1.9.3-p0 :002 > def method_missing(sym, *args); #v[sym]; end
=> nil
ruby-1.9.3-p0 :003 > a
(irb):2: stack level too deep (SystemStackError)
-bash-3.2$
I ran with -f to avoid loading any irbrc stuff.
I'm expecting to get nil when I input a. What's going on, and is there a workaround? I tried wrapping a with a begin/rescue Exception block but that didn't do anything.
This also happens with 1.9.2, but not 1.9.1.
More strange behavior:
-bash-3.2$ irb -f
irb(main):001:0> #v = {}
=> {}
irb(main):002:0> def method_missing(sym, *args); #v[sym]; end; 5.times { p a }
nil
nil
nil
nil
nil
=> 5
irb(main):003:0> a
(irb):2: stack level too deep (SystemStackError)
-bash-3.2$
This tells me that there's a bug in irb, or that some obscure bug in ruby is being triggered by irb. Also, after defining method_missing, even methods that exist like local_variables or eval cause the error.
Looks like defining it as a singleton method works:
def self.method_missing(sym, *args); #v[sym]; end
Defining it as a top-level method replaces BasicObject#method_missing, which probably affected some irb internals like Phrogz said.

Resources