When I run vim or top from a console they are able to take over rendering the whole console. When I quit I'm then returned to the console.
Is it possible to do this from ruby? As a simple example, how would I do the following
# Rakefile
task :clock do
loop do
console.render Time.now
sleep 1
end
end
when I run this the console would be cleared and the first line would show the time. When I quit I'd then continue the console session as it was before I ran rake clock.
Update
Having checked the tictactoe example for ruby curses here's an implementation of the clock example. I've shown the clock on random lines to demonstrate refreshing the whole console.
#!/usr/bin/env ruby
require 'curses'
loop do
Curses.clear
Curses.setpos(rand * 10, 0)
Curses.addstr(Time.now.to_s);
Curses.refresh
sleep 1
end
You're looking for the Ruby curses library which gives you full control over the screen: positioning, color, &c.
It's not a well document library, but a Stackoverflow search for "[ruby] curses" will give you links to examples.
Related
While starting an assignment (Towers of Hanoi), I leave my code in a very basic state while I ponder the logic of how to continue.
while arr3.count < 6
puts "Move ring FROM which tower?"
from = gets.chomp
puts "Move ring TO which tower?"
to = gets.chomp
end
Before I can start building the rest of the app, however, gets seems to fall through without any input from me, and the second puts displays on the screen. This continues looping every, say, 30 seconds or so. Should I assume this is a feature of online interpreters (like codeacademy labs)?
Now I'm distracted from continuing the assignment and have to find a better place to do my code.
I'm installing Aptana (based on some advice on this forum) to see if I can get a better environment to do my assignments. Or do most people use a text editor then run their .rb file through the windows console window?
Thx
So let's say pretty often a script runs that opens a browser and does web things:
require 'watir-webdriver'
$browser = Watir::Browser.new(:firefox, :profile => "botmode")
=> #<Watir::Browser:0x7fc97b06f558 url="about:blank" title="about:blank">
It could end gracefully with a browser.close, or it could crash sooner and leave behind the memory-hungry Firefox process, unnoticed until they accumulate and slow the server to a crawl.
My question is twofold:
What is a good practice to ensure that even in case of script failure anywhere leading to immediate error exit, the subprocess will always get cleaned up (I already have lots of short begin-rescue-end blocks peppered for other unrelated small tests)
More importantly, can I simply remember this Watir::Browser:0x7fc97b06f558 object address or PID somehow and re-assign it to another $browser variable in a whole new Ruby process, for example irb? I.e. can an orphaned browser on webdriver be re-attached later in another program using watir-webdriver on the same machine? From irb I could then get in and re-attach to the browser left behind by the crashed Ruby script, to examine the website it was on, check what went wrong, what elements are different than expected, etc.
Another hugely advantageous use of the latter would be to avoid the overhead of potentially hundreds of browser startups and shutdowns per day...best to keep one alive as sort of a daemon. The first run would attempt to reuse a previous browser object using my specially prepared botmode profile, otherwise create one. Then I would deliberately not call $browser.close at the end of my script. If nothing else I run an at job to kill the Xvfb :99 display FF runs inside of at the end of the day anyway (giving FF no choice but to die with it, if still running). Yes I am aware of Selenium standalone jar, but trying to avoid that java service footprint too.
Apologies if this is more a basic Ruby question. I just wasn't sure how to phrase it and keep getting irrelevant search results.
I guess, U cant just remember the variable from another process. But the solution might be creating a master process and process your script in loop in thread, periodically checking the browser running state. I'm using some thing similar in my acceptance tests on Cucumber + watir. So it will be some thing like that:
require 'rubygems'
require 'firewatir' # or watir
#browser = FireWatir::Firefox.new
t = Thread.new do
#browser.goto "http://google.com"
#call more browser actions here
end
while not_exit?
if t.stop?
# error occurred in thread, restart or exit
end
if browser_live?
# browser was killed for a some reason
# restart or exit
end
end
#browser.close
not_exit? - can be over TRAP for the ctrl+C
browser_live? - you can check if firefox browser running with processes listings
It is quite tricky but might work for you
You can use DRb like this:
browsers pool:
require 'drb'
require 'watir'
browser = Watir::Browser.new :chrome
DRb.start_service 'druby://127.0.0.1:9395', browser
gets
and then from test script use this browser:
require 'drb'
browser = DRbObject.new_with_uri 'druby://127.0.0.1:9395'
browser.goto 'stackoverflow.com'
I'm pretty sure that at the point ruby exits, any handles or pointers to something like a browser object would become invalid. So re-using something in a later ruby process is likely not a good approach. In addition I might be wrong on this, but it does seem that webdriver is not very good at connecting to a running browser process. So for your approach to work it would really all need to be wrapped by some master process that was calling all the tests etc.. and hey wait a sec, that's starting to sound like a framework, which you might already (or perhaps should be) using in the first place.
So a better solution is probably to look at whatever framework you are using to run your tests and investigate any capability for 'setup/teardown' actions (which can go by different names) which are run before and after either each test, groups of tests, or all tests. Going this way is good since most frameworks are designed to allow you to run any single test, or set of tests that you want to. And if your tests are well designed they can be run singly without having to expect the system was left in some perfect state by a prior test. Thus these sorts of setup/teardown actions are designed to work that way as well.
As an example Cucumber has this at the feature level, with the idea of a 'background' which is basically intended as a way to dry out scenarios by defining common steps to run before each scenario in a feature file. (such as navigating to and logging into your site) This could include a call to a series of steps that would look to see if a browser object existed, and if not create one. However you'd need to put that in every feature file which starts to become rather non dry.
Fortunately cucumber also allows a way to do this in one place via the use of Hooks. You can define hooks to run before steps, in the event of specific conditions, 'before' and 'after' each scenario, as well as code that runs once before any scenarios, and code defined to run 'at_exit' where you could close the browser after all scenarios have run.
If I was using cucumber I'd look at the idea of a some code in env.rb that would run at the start to create a browser, complemented by at_exit code to close the browser. Then perhaps also code in a before hook which could check to see that the browser is still there and re-create it if needed, and maybe logout actions in a after hook. Leave stuff like logging in for the individual scenarios, or a background block if all scenarios in a feature login with the same sort of user.
Not so much a solution but a workaround for part 1 of my question, using pkill. Posting here since it turned out to be a lot less trivial than I had hoped.
After the ruby script exits, its spawned processes (which may not at all belong in the same PID tree anymore, like firefox-bin) have a predictable "session leader" which turned out to be the parent of the bash shell calling rubyprogram.rb in my case. Available as $PPID in Bash, for when you have to go higher than $$.
Thus to really clean up unwanted heavyweight processes eg. after a ruby crash:
#!/bin/bash
# This is the script that wraps on top of Ruby scripts
./ruby_program_using_watirwebdriver_browser.rb myparams & # spawn ruby in background but keep going below:
sleep 11 # give Ruby a chance to launch its web browser
pstree -panu $$ # prints out a process tree starting under Bash, the parent of Ruby. Firefox may not show!
wait # now wait for Ruby to exit or crash
pkill -s $PPID firefox-bin # should only kill firefox-bin's caused above, not elsewhere on the system
# Another way without pkill, will also print out what's getting killed if anything:
awk '$7=="firefox-bin" && $3=="'$PPID'" {print $1}' <(ps x -o pid,pgid,sess,ppid,tty,time,comm) | xargs -rt kill
OPTIONAL
And since I use a dedicated Xvfb Xwindows server just for webdriving on DISPLAY :99, I can also count on xkill:
timeout 1s xwininfo -display :99 -root -all |awk '/("Navigator" "Firefox")/ {print $1}' |xargs -rt xkill -display :99 -id
# the timeout is in case xkill decides to wait for user action, when window id was missing
Just an update on part 2 of my question.
It seems one CAN serialize a Watir:Browser object with YAML, and because it's text-based the contents were quite interesting to me (e.g. some things I've only dreamed of tweaking hidden inside private elements of private classes...but that's a separate topic)
Deserializing from YAML is still trouble. While I haven't tested beyond the first try it gives me some kind of reg exp parse error...not sure what that's about.
(more on that at at how to serialize an object using TCPServer inside? )
Meanwhile, even attempting to serialize with Marshal, which is also built-in to Ruby but stores in binary format, results in a very reasonable-sounding error about not being able to dump a TCPServer object (apparently contained within my Watir:Browser pointed to by $browser)
All in all I'm not surprised at these results, but still pretty confident there is a way, until Watir arrives at something more native (like PersistentWebdriver or how it used to be in the days of jssh when you could simply attach to an already running browser with the right extension)
Until then, if serialization + deserialization to a working object gets too thorny I'll resort to daemonizing a portion of my Ruby to keep objects persistent and spare the frequent and costly setup/teardowns. And I did take a gander at some established (unit testing) frameworks but none seem to fit well yet within my overall software structure--I'm not web testing after all.
I would like to talk to a interactive bash process.
Here is an example, so you know what I want to archieve:
Program starts a new bash process.
User types "ls" into my program.
Program sends this command to the bash process.
Program reads all available output of the bash (including the prompt) and displays it back to the user.
GOTO 1
As you can guess, there is much room for nifty manipulations here and there... ;-)
It would be wonderful if this also worked for subprocesses (started by the bash process) and curses-based programs.
I would like to implement this functionality in Ruby, and already have experimented with IO.popen, but strange things happen. You are also welcome to do this in other languages.
Ok, I've found a solution. This work pretty nicely, you can even start vim inside it :-)
require "pty"
system("stty raw -echo")
PTY.spawn("bash -i") do |pin, pout|
Thread.new do
loop do
pout.print STDIN.getc.chr
end
end
loop do
print pin.sysread(512)
STDOUT.flush
end
end
This does the following:
enable character-wise input (limited to UNIXoids, I'm afraid)
create a pseudo-TTY, start a interactive bash session inside
forward each character from STDIN to the bash
print every output back to the user
Have you tried using the Session gem?
http://rubygems.org/gems/session
https://github.com/ahoward/session (Homepage with introduction.)
I don't have any experience with it, but the README seems to describe what you want. It's description says, "session kicks the ass", so it should be fun/productive to play with it in any case.
Currently, when I get an error on an erb template (for use with HTTPServer/cgi) I do the following:
If it's a small change, revert, save and retest.
For a large change or new file, delete or comment 1/2 the code, and retest. Perform a binary search until I've deleted/found the broken code.
The call stack doesn't seem to correspond to anything in my .rhtml file.
(erb):6:in `block in <main>'
/opt/local/lib/ruby/1.9.1/erb.rb:753:in `eval'
/opt/local/lib/ruby/1.9.1/erb.rb:753:in `result'
bin/correct.rb:45:in `block in <main>'
/opt/local/lib/ruby/1.9.1/webrick/httpservlet/prochandler.rb:26:in `call'
Not sure if this is applicable to this problem but maybe it will help someone. I'm using rails 5 and if you put
<% debugger %>
in your html.erb file it will pause the terminal window that your rails server is running in. From there you can debug whatever params or variables your html.erb file has.
As Daniel said, most times the error message will help you to quickly find where the error is.
There are indeed some occasions on which it doesn't.
The dumber, faster way to do that binary search is to just insert a wrong line, like
<%= the_error_is_after_this_line %>
and then move the line until you find the exact row.
I'm not one of those bright programmers who can write tons of lines per time which just work; i usually develop by small steps and reload the page on browser each time.
That said, the better way to avoid hard to debug views (or methods, or whatever) is to write simple, short ones. My rule of thumb is that I must be able to read the whole view (or method) in the editor window, unless it's just plain html.
Always use helpers and partial views. Can you count more than two () or [] in a line of your erb view? If yes, use a helper.
Can you count more than two or three blocks in your view? Use some partials.
In general Erb errors tell you where they occurred. For instance here your error is on line 6 of the erb file. You have omitted the error message that came with the backtrace, but that usually tells you what kind of error to look for. For instance, in my simple test here:
NameError: undefined local variable or method `asdf' for main:Object
from (erb):7
from (irb):6
It is clear enough what is going wrong and where.
Can you post more information about your error and the erb that caused it?
On Rails 5 you can find the gem 'byebug' by default at Gemfile:
group :development, :test do
# Call 'byebug' anywhere in the code to stop execution and get a debugger console
gem 'byebug', platforms: [:mri, :mingw, :x64_mingw]
end
Then you can use byebug on your controller, put it wherever you want and many times you need, it functions like a 'breakpoint' and finally run your server $ rails server
class UsersController < ApplicationController
byebug
end
At command line write help for options, normally use letter 'c' to continue to the next breakpoint, or the letter 'n' to advance step by step and ctrl+d to exit.
(byebug) help
break -- Sets breakpoints in the source code
catch -- Handles exception catchpoints
condition -- Sets conditions on breakpoints
continue -- Runs until program ends, hits a breakpoint or reaches a line
debug -- Spawns a subdebugger
delete -- Deletes breakpoints
disable -- Disables breakpoints or displays
display -- Evaluates expressions every time the debugger stops
down -- Moves to a lower frame in the stack trace
edit -- Edits source files
enable -- Enables breakpoints or displays
finish -- Runs the program until frame returns
frame -- Moves to a frame in the call stack
help -- Helps you using byebug
history -- Shows byebug's history of commands
info -- Shows several informations about the program being debugged
interrupt -- Interrupts the program
irb -- Starts an IRB session
kill -- Sends a signal to the current process
list -- Lists lines of source code
method -- Shows methods of an object, class or module
next -- Runs one or more lines of code
pry -- Starts a Pry session
quit -- Exits byebug
restart -- Restarts the debugged program
save -- Saves current byebug session to a file
set -- Modifies byebug settings
show -- Shows byebug settings
skip -- Runs until the next breakpoint as long as it is different from the current one
source -- Restores a previously saved byebug session
step -- Steps into blocks or methods one or more times
thread -- Commands to manipulate threads
tracevar -- Enables tracing of a global variable
undisplay -- Stops displaying all or some expressions when program stops
untracevar -- Stops tracing a global variable
up -- Moves to a higher frame in the stack trace
var -- Shows variables and its values
where -- Displays the backtrace
(byebug)
Other option to display the debug(params):
In the app/views/layouts/application.html.erb file under render footer and above put the next:
<%= debug(params) if Rails.env.development? %>
Finally I share this options as I know as a newbie in Ruby on Rails. Hope this helps.
Source of some help: https://rubyplus.com/articles/3631-Debugging-using-ByeBug-Gem-in-Rails-5
I'm currently playing with wxRuby and RubyMSN to learn to program desktop-programs. I know it is a hard task instead of just crating a notepad etc, but I need a bigger task than a notepad.
I now do manage to use them by them self, but I cant get them to work together. The problem is the loop.
RubyMSN wants to have an endless loop like
while true
sleep 1
end
or using the GUI's mainloop or something
I currently have this code as the loop
TheApp.new.main_loop()
while true
sleep 1
end
I have my window working, and the main_loop doing something. But I cant log in, it's like I doesn't have any loop (from the tutorial), I only get one debug line. But as soon as I close the window and lets the endless loop do it's job it works like a charm.
Someone ?
Worked for me. Try this: copy the minimal sample from the wxruby distribution, and modify minimal.rb so that you start your msn thread just before the wx main loop:
require 'msn/msn'
conn = MSNConnection.new("rubybot#channelwood.org", "secretpassword123")
conn.start
# Wx::App is the container class for any wxruby app. To start an
# application, either define a subclass of Wx::App, create an instance,
# and call its main_loop method, OR, simply call the Wx::App.run class
# method, as shown here.
Wx::App.run do
self.app_name = 'Minimal'
frame = MinimalFrame.new("Minimal wxRuby App")
frame.show
end
You'll need to symlink the msn directory inside the minimal directory to get the require statement working, of course.
You don't need the while true {sleep 1} loop; that's just to prevent the program from exiting so that your msn thread can keep running. The wx main loop accomplishes the same purpose.