Strange Rails console behaviour - ruby-on-rails

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.

Related

Breakpoints with pry-byebug don't trigger in the console

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

Byebug breakpoint setting and continuation trouble

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.

Can I display the log of system call in Ruby?

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.

How do I Quit IRB from the command line? (Using terminal on mac)

Basically, I'm typing along just fine in terminal, using IRB to run ruby commands:
2.0.0-p0 :014 > bank_account.withdraw(2222)
=> -1222
But sometimes I accidentally miss out a quotation mark.
2.0.0-p0 :020 > BankAccount.create_for("Jim","Johnson)
2.0.0-p0 :021"> bank_account.withdraw(333)
If you look carefully, you'll see that the speech mark I missed out appears next to the line number on the left, next to the patch version.
From here on in, that speech mark appears everytime I run a command! And it stops the commands working:
2.0.0-p0 :021"> BankAccount.create_for("Julian","Hurley")
2.0.0-p0 :022"> BankAccount.create_for("Katt","Smith")
2.0.0-p0 :023"> exec($0)
What I want to know is, how do I get rid of that quotation mark? Or quit IRB from the command line in order to reset it?
If you haven't closed a quote, just put a quote in and hit return.
Exiting from the console can be done by typing exit, though in the circumstance your are would need to hit Control - C
Control - C followed by Control - Z.
I hope it helps!
I was having the same problem. To exit irb within the terminal, type exit.
Use Ctrl-D, it is an end-of-input for irb. If you are in the middle of some command, use Ctrl-C first to terminate the input of this command.
Type quit() and hit Enter to exit ruby.
If you're in the middle of a multi-line block (according to the interpreter), hit Ctrl+C to break out of it.
Then you can do any of the following to quit:
exit (or exit())
quit (or quit())
irb_exit (or irb_exit())
Ctrl+D (sends the EOF character)

puts doesn't print stuff to console

i'm using POW for local rails development. i don't know why, but i can't print or puts information to my development.log. i want to puts the content of variables to console / log from my controller. any advice?
i read my logs with tail -f logs/development.log
thanks!
Instead of puts, try logger.info(). Logging in Rails is very flexible, but it does mean that you might not be able to use the simplest tools sometimes.
If you're doing debugging and only want to see some messages in the logs you can do the following:
Rails.logger.debug("debug::" + person.name)
and
$ pow logs | grep debug::
now you'll only see logging messages that start with debug::
Another option is to use the rails tagging logger, http://api.rubyonrails.org/classes/ActiveSupport/TaggedLogging.html.
logger = ActiveSupport::TaggedLogging.new(Logger.new(STDOUT))
logger.tagged('BCX') { logger.info 'Stuff' } # Logs "[BCX] Stuff"
$ pow logs | grep BCX
For anyone who still can't get it to work, remember that Ruby doesn't use semicolons. They are only used to chain commands. I was adding them at the end due to muscle memory (coming from PHP), so the ruby console thought I was still entering commands:
irb(main):001:0> puts "hi";
irb(main):002:0* puts "hi"
hi
hi
=> nil
Hope this helps someone.

Resources