Byebug does not update local variable on Ubuntu - ruby

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.

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)

How to access element in array via command line in ruby?

Given a simple code in file test.rb:
def todo_list(todo_selector)
library = ["Get a cat", "Get a dog", "Build a fighting ring"]
puts "Your current step in todo-list is:\n#{library[todo_selector]}"
end
ARGV.each { |todo| todo_list(todo_selector) }
How am I able to call this method with an index via command line?
Normally I would use test.rb 1, but I am getting this error:
Traceback (most recent call last):
2: from test.rb:17:in `<main>'
1: from test.rb:17:in `each'
test.rb:17:in `block in <main>': undefined local variable or method `todo_selector' for main:Object (NameError)
Did you mean? todo_list
What am I doing wrong?
Try this way for one element, take care to convert String into Integer in order to access the Array by index.
selector = ARGV[0].to_i
todo_list(selector)
For an array of arguments: ARGV.each{ |i| todo_list(i.to_i) }

__FILE__ returns different value when using binding.pry

__FILE__ returns the path of the current Ruby script file.
One potentially significant problem is that, if using binding.pry, __FILE__ evaluates to (pry). It is potentially problematic to have __FILE__ evaluate to different values depending on whether it is evaluated in the context of binding.pry. For example,
$stdout.print "****************************************\n\n"
$stdout.print "FILE: #{__FILE__}\n\n"
$stdout.print "****************************************\n\n"
binding.pry
When the script pauses at binding.pry, I get:
__FILE__
# >> (pry)
Does anyone know any mechanism to get the path of the current file even in the context of binding.pry?
Use _file_ instead of __FILE__. For example, given two files:
# foo.rb
require 'pry'
require './bar'
binding.pry
b = Bar.new
and:
# bar.rb
require 'pry'
class Bar
def initialize
binding.pry
end
end
Run them with ruby foo.rb:
ruby foo.rb
From: /Users/username/foo.rb # line 3 :
1: require 'pry'
2: require './bar'
=> 3: binding.pry
4: b = Bar.new
(main):1 ⇒ _file_
=> "/Users/username/foo.rb"
(main):2 ⇒ exit
From: /Users/username/bar.rb # line 4 Bar#initialize:
3: def initialize
=> 4: binding.pry
5: end
(#<Bar:0x00007fbb6caaff08>):1 ⇒ _file_
=> "/Users/username/bar.rb"
_file_ and any other local variable names can be found in binding.local_variables.
Sergio Tulentsev made a simple suggestion, assign __FILE__ to a variable before invoking binding.pry.
anothermh, mentioned _file_ which is available in binding pry.
In the end, I combined the two answers:
# When in the context of binding.pry, __FILE__ resolves to '(pry)',
# binding contains the local variable _file_ which always resolves to
# the current file, even when being evaluated in the context of binding.pry .
# _file_ is only available, in binding. This does the trick:
current_file = __FILE__.downcase == '(pry)' ? _file_ : __FILE__

Pry doesn't work when launched from method invoked by RSpec test

I'm trying to use Pry with RSpec.
Goal is to be able to drop binding in method and debug it.
Here is what I have.
lib/play.rb
class Play
def self.hello
print 'Hello world!'
require 'pry'; binding.pry
end
end
spec/play_spec.rb
require_relative '../lib/play'
describe Play do
it 'Play#hello should print message' do
expect {Play.hello}.to output('Hello world!').to_stdout
#require 'pry'; binding.pry
end
end
If I uncomment binding in spec file and run
rspec
I'm getting into Pry which behaves as expected
Frame number: 0/23
From: /Users/iiezhachenko/Documents/Repos/bdd-ruby- playground/spec/play_spec.rb # line 6 :
1: require_relative '../lib/play'
2:
3: describe Play do
4: it 'Play#hello should print message' do
5: expect {Play.hello}.to output('Hello world!').to_stdout
=> 6: require 'pry'; binding.pry
7: end
8: end
[1] pry(#<RSpec::ExampleGroups::Play>)> ls
RSpec::Core::MemoizedHelpers#methods: is_expected should should_not subject
RSpec::Core::Pending#methods: pending skip
RSpec::Mocks::ArgumentMatchers#methods:
If I comment out binding.pry in spec fill, put it in method which is tested and invoke "rspec" again. I'm getting into completely messed Pry.
[1] pry(Play)> ls
[2] pry(Play)> fghjk
[3] pry(Play)> kweutyalfh
[4] pry(Play)> exit
F
Failures:
1) Play Play#hello should print message
Failure/Error: expect {Play.hello}.to output('Hello world!').to_stdout
expected block to output "Hello world!" to stdout, but output "Hello world!\n\e[1mFrame number:\e[0m 0/32\n\n\e[1mFrom:\e[0m /Users/iiezhachenko/Documents/Repos/bdd-ruby-playground/lib/play.rb # line 4 Play.hello:\n\n \e[1;34m2\e[0m: \e[32mdef\e[0m \e[1;36mself\e[0m.\e[1;34mhello\e[0m\n \e[1;34m3\e[0m: print \e[31m\e[1;31m'\e[0m\e[31mHello world!\e[1;31m'\e[0m\e[31m\e[0m\n => \e[1;34m4\e[0m: require \e[31m\e[1;31m'\e[0m\e[31mpry\e[1;31m'\e[0m\e[31m\e[0m; binding.pry\n \e[1;34m5\e[0m: \e[32mend\e[0m\n\n\e[0G\e[1m\e[1;34mPlay.methods\e[0m\e[0m: hello\n\e[1m\e[1;34mlocals\e[0m\e[0m: _ __ _dir_ _ex_ _file_ _in_ _out_ _pry_\nNameError: undefined local variable or method `fghjk' for Play:Class\nfrom (pry):1:in `hello'\nNameError: undefined local variable or method `kweutyalfh' for Play:Class\nfrom (pry):2:in `hello'\n"
Diff:
## -1,2 +1,17 ##
Hello world!
+Frame number: 0/32
+
+From: /Users/iiezhachenko/Documents/Repos/bdd-ruby-playground/lib/play.rb # line 4 Play.hello:
+
+ 2: def self.hello
+ 3: print 'Hello world!'
+ => 4: require 'pry'; binding.pry
+ 5: end
+
Play.methods: hello
+locals: _ __ _dir_ _ex_ _file_ _in_ _out_ _pry_
+NameError: undefined local variable or method `fghjk' for Play:Class
+from (pry):1:in `hello'
+NameError: undefined local variable or method `kweutyalfh' for Play:Class
+from (pry):2:in `hello'
# ./spec/play_spec.rb:5:in `block (2 levels) in <top (required)>'
Anyone faced such issue?
As the answer by OP indicates, the problem involves console output suppression, which can inadvertently break Pry.
If you check your spec/spec_helper.rb file, there is likely some code inside the RSpec configuration block that is referring to $stderr and/or $stdout. Removing those lines of code should fix the problem.
For other examples of how this output might be getting suppressed, see the answers to this question: Suppress console output during RSpec tests
Issue resolved by removing stdout capturing from test. Thanks everyone.

IRB called from byebug loses context

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.

Resources