I'm trying to use pry and pry-byebug to step through the execution of some code in a Rails console. I started the console with
pry -r ./config/environment
I then set a breakpoint:
break Foo#bar
Then make a new Foo and call bar on it:
Foo.new.bar
I expected step into Foo#bar, but instead the method just executed normally.
Is there some way to get this workflow to work?
I found the answer: the debugger is not re-entrant. So you need to do this:
[1] pry(main)> binding.pry
[1] pry(main)> break Foo#bar
Breakpoint 1: Foo#bar (Enabled) :
6: def bar
7: end
[2] pry(main)> c # continue and exit the debugger we started on the first line
=> nil
[3] pry(main)> Foo.new.bar
Breakpoint 1. First hit.
Here is how I usually use pry-byebug
Add a call to binding.pry to the first line of the method Foo#bar
Run rails console
Call Foo.new.bar
You should see the pry REPL now
Hmm, when I use pry-byebug to debug my code I use in the following way:
First require the pry-byebug gem in the beginning of the coding
require 'pry-byebug'
def main # Do some coding
puts "Hello"
binding.pry # break point here
puts "World"
end
main
Then when running it my terminal will return enter irb mode and return:
> 3: def main
> 4: puts "Hello"
> 5:
> 6: binding.pry
> => 7: puts "World!"
> 8: end
>
> [1] pry(main)>
So the code indicates where I am right now, and from that point I could check every variable read before the breakpoint (on line 6). The breakpoint indicates the terminal have not yet read things after line 6, so if I had variables there, the terminal would not recognize them.
I could then type next, so binding.pry would jump to the next binding.pry point available or run through the whole code. Or I could simply type continue.
What is very important to remeber is to remove the require 'pry-byebug' and all the breakpoints lines before commiting your code, because we don't want the code to get stuck in those points, right? The user might not know how to deal with it :)
Hope it helped! First time trying to contribute to this awesome community :D
Related
I've experienced an odd interface glitch.
[44, 53] in /document.rb
44: code
45: code
46:
47: def code
48: byebug
=> 49: code
50: code
51: code
52: end
53:
(byebug) {here is where you type}
When I type, the characters are not displayed at all. I can type p "yo" or whatever I want, and when I hit enter it runs the code. Essentially I can use byebug in a pinch, but it's really frustrating when I can't see what I'm typing.
I've used byebug in the past with this same laptop, and this issue is fairly recent.
I was assisting a friend, and when he used byebug the same issue happened. I haven't been able to find anything online.
TL;DR: Add this line in config/puma.rb:
# Specifies the `worker_timeout` threshold that Puma will use to wait before
# terminating a worker in development environments.
worker_timeout 3600 if ENV.fetch("RAILS_ENV", "development") == "development"
Reproducing & Why this is happening
In development mode, set a debugger in a controller action and send a request to this action (e.x. index). After 60 seconds Puma, Rails' default server, will terminate the worker. Unfortunately, the next time a debugger is triggered you will be unable to see any text you type in the terminal.
This is a known bug and is fixed in Rails 7+. The above line was added to change Puma's worker timeout to a more appropriate level (1 hour) when in development mode.
Other Causes
As u/casper pointed out in a comment above, Spring can also cause similar behaviour. Stop your server and run bin/spring stop and this may resolve your issue.
If you're experience only some text appear when you type, this may be a result of parallelized tests. For example, if you type, "Hello World" but only "Hol" appears (i.e. some letters), you can disable parallelized tests following u/sajad-rastegar's advice above. Simply comment this line in test/test_helper.rb: parallelize(workers: :number_of_processors).
This problem occurs when the tests run in parallel. Commenting this line in test_helper should fix the problem:
parallelize(workers: :number_of_processors)
I am trying to learn Byebug and am following the (https://github.com/deivid-rodriguez/byebug/blob/master/GUIDE.md) and I am getting stuck with setting a breakpoint and continuing after the breakpoint is set. After I set the breakpoint for line 5 and run continue, Byebug quits the session. Can someone see what I am doing wrong?
$byebug hanoi.rb
[1, 10] in /Users/jackburum/ruby/byebug-testing/hanoi.rb
1: #
2: #
3: #
=> 4: def hanoi(n, a, b, c)
5: hanoi(n - 1, a, c, b) if n - 1 > 0
6:
7: puts "Move disk #{a} to #{b}"
8:
9: hanoi(n - 1, c, b, a) if n - 1 > 0
10: end
(byebug) break 5
Successfully created breakpoint with id 1
(byebug) continue
$byebug hanoi.rb
If I run the next command instead of continue, the same issue occurs...
[1, 10] in /Users/jackburum/ruby/byebug-testing/triangle.rb
=> 1: def triangle(n)
2: tri = 0
3:
4: 0.upto(n) { |i| tri += i }
5:
6: tri
7: end
8:
9: # if __FILE__ == $triangle.rb
10: # t = triangle(3)
(byebug) break 2
Successfully created breakpoint with id 1
(byebug) next
$
are you meaning to use next here? continue is the same control+d, and will continue to run your code until either another breakpoint is reached or the code ends.
I'm figuring that when you type continue, the rest of your script runs and the program exits because there isn't another breakpoint.
By the way, it might be worth trying the pry gem instead of byebug. Unlike byebug, copy-pasting multi-line code works in pry and there are a number of other useful features such as source-code browsing and syntax highlighting. Although it doesn't come with 'next' or 'continue' out the box, you can install the pry-byebug gem to get these.
Edit
From the additional info you've given, this seems to actually be the expected behavior here. Here's what you need to understand about breakpoints:
They will not follow a downward scope change. For example, say I've written a method like this:
def my_method
puts "my method started"
byebug
5.times { "do something in a loop" }
end
my_method()
puts "my method is done"
puts "the program will end now"
When you run the code with ruby myfile.rb, the code gets to line 6 before pausing on the breakpoint. Since the breakpoint is inside the method body, it won't be activated until the method is actually called.
What would happen if you typed next? Would you have to type it 5 times to get through the 5.times {} loop? The answer is no, and this is because there is a downward scope change into the iterator. In Javascript this "scope change" is more clear because you use the function keyword to show an anonymous function (and therefore a scope change). But in Ruby, blocks are actually syntactic sugar for Procs, which are anonymous functions and therefore introduce a scope change. I'm not sure of the exact reason, but moving into a method body also entails a downward scope change.
So when you press next, what actually happens is that it moves to the puts "my method is done" call. Although the byebug keyword is inside the method, to return to the scope of the method caller is an 'upward' scope change and is expected. Typing next again would move to the puts "my program will end now" line. Typing it again would get to the end of the code and exit the program.
If you needed to pause at each iteration in the loop, you could put the breakpoint inside the loop block i.e. 5.times { byebug }
To bring it back to your example - when you call your script with the byebug executable (i.e. byebug myprogram.rb), the initial scope is top-level. Typing next will skip over any functions or loops. I don't see this being practical for anything other than very small programs, so it's better to place the byebug keyword in your code and call the program with the ruby executable instead, i.e. ruby myprogram.rb
It's a small detail, but breakpoints are ignored when they are the last line in a program. To prevent this, put anything after the breakpoint, even something as simple as exit.
By the way, all this scope stuff applies to pry too as far as I'm aware.
I need to call a command(in a sinatra or rails app) like this:
`command sub`
Some log will be outputed when the command is executing.
I want to see the log displaying continuously in the process.
But I just can get the log string after it's done with:
result = `command sub`
So, is there a way to implement this?
On windows i have the best experience with IO.popen
Here is a sample
require 'logger'
$log = Logger.new( "#{__FILE__}.log", 'monthly' )
#here comes the full command line, here it is a java program
command = %Q{java -jar getscreen.jar #{$userid} #{$password}}
$log.debug command
STDOUT.sync = true
begin
# Note the somewhat strange 2> syntax. This denotes the file descriptor to pipe to a file. By convention, 0 is stdin, 1 is stdout, 2 is stderr.
IO.popen(command+" 2>&1") do |pipe|
pipe.sync = true
while str = pipe.gets #for every line the external program returns
#do somerthing with the capturted line
end
end
rescue => e
$log.error "#{__LINE__}:#{e}"
$log.error e.backtrace
end
There's six ways to do it, but the way you're using isn't the correct one because it waits for the process the return.
Pick one from here:
http://tech.natemurray.com/2007/03/ruby-shell-commands.html
I would use IO#popen3 if I was you.
I am working on ROR app , with ruby debugger. This is my code:
def render(d)
debugger
folder=d.folders
folders,empty_folders=check_empty_folder(folder)
c = cost(folders)
end
Now in console the break point at folders=d.folders . Now if i do next near around 30 times then it come to next line in this function folders,empty_folders after going through different ruby source file.
Is there any command I can simply go into next line of function in spite of source code.
When I run a multi-line statement in the Rails 3.0.1 console, pressing enter doesn't actually run the statement. Instead, it goes to a new console line, and the cursor has been tabbed to the right. Then I have to run a basic line (like p "hey"), and then the multi-line statement will run.
ruby-1.9.2-p0 > images = Image.all;images.each do |im|; if im.imagestore_width.blank?;im.save;end;
ruby-1.9.2-p0 > p "hey"
I've been doing it like this for awhile and it's been working okay. But now I've got a problem in the console and it might be related. When I ran the above code, instead of it working like it normally does, it just went to a new console line with a ? added
ruby-1.9.2-p0 > images = Image.all;images.each do |im|; if im.imagestore_width.blank?;im.save;end;
ruby-1.9.2-p0 > p "hey"
ruby-1.9.2-p0 ?>
When it does this, I can't exit the console
ruby-1.9.2-p0 ?> exit
ruby-1.9.2-p0 ?> ^C
Are these problems related? How can I fix them?
In the line:
images = Image.all;images.each do |im|; if im.imagestore_width.blank?;im.save;end;
You have an end to close the if but not an end to close the do block of the each.
This is why the console is redisplaying the prompt asking for more input before executing your statements.
Try:
images = Image.all;images.each do |im|; if im.imagestore_width.blank?;im.save;end;end
Notice, you will see the same behaviour with brackets. irb or console won't execute until the brackets balance e.g.
irb(main):010:0> (3 *
irb(main):011:1* (2 + 1)
irb(main):012:1> )
=> 9
Dunno what's wrong with irb/console but your ruby code could look a lot nicer:
images = Image.all.each { |im| im.save if im.imagestore_width.blank? }
The general consensus is to use {} rather than do/end for single line blocks in ruby.