Ruby personal notes
Use next/redo to jump to the beginning. Use break to break out the program.
Altering Loop Control
cont = "y"
while (cont == "y")
print ("Enter a numerator: ")
num = Integer(gets)
print("Enter a denominator: ")
denom = Integer(gets)
if denom == 0 then
next
# or 'redo'
# or 'break' to exit
end
puts(num / denom)
print ("More? (y/n) ")
cont = gets
cont = cont.chomp
end
Using if statement in while statement
answer = "Watson"
tries = 0
while tries < 3
print("What is the name of the computer that played on Jeopardy? ")
response = gets
response = response.chomp
tries += 1
if response == "Watson"
puts ("That's right!")
exit
elsif tries == 3
puts ("Sorry. The answer is Watson.")
exit
else
puts ("Sorry. Try again")
end
end
Split a string
" now's the time".split #=> ["now's", "the", "time"]
" now's the time".split(' ') #=> ["now's", "the", "time"]
# split by word
" now's the time".split(/ /) #=> ["", "now's", "", "the", "time"]
"1, 2.34,56, 7".split(%r{,\s*}) #=> ["1", "2.34", "56", "7"]
# split by letter
"hello".split(//) #=> ["h", "e", "l", "l", "o"]
"hello".split(//, 3) #=> ["h", "e", "llo"]
"hi mom".split(%r{\s*}) #=> ["h", "i", "m", "o", "m"]
Block
- A block need to associate with a method call.
- A block can be between do-end with a method call.
- A block can have parameters between pipes like | param |
- A method can have parameters with block as well
- each method can take a block
# 1.
# a block do nothing
# use {} for a single line
{ puts "Echo"}
# associate with a method call
3.times { puts "Echo"}
# 2. Use do-end for multiple lines
10.times do
puts "situp"
end
# 3. (count from 0-9)
10.times do |number|
puts "#{number} situp"
end
# 4. (count from 1-10)
1 upto(10) do |number|
puts "#{number} situp"
end
# 5.
movies. each do |movie|
movie.thumbs_up
puts movie
end
Select
select takes a block. All are the same in the followings.
numbers.select do |number|
number>5
end
numbers.select{ |number| number>5 }
numbers.select{ |n| n>5}
Rspec
movie_spec.rb
require_relative 'movie'
describe Movie do
before do
@initial_rank = 10
@movie = Movie.new("goonies", @initial_rank)
end
it "has a capitalized title" do
@movie.title.should == "Goonies"
end
it "has an initial rank" do
@movie.rank.should == 10
end
it "has a string representation" do
@movie.to_s.should == "Goonies has a rank of 10"
end
it "increases rank by 1 when given a thumbs up" do
@movie.thumbs_up
@movie.rank.should == @initial_rank + 1
end
it "decreases rank by 1 when given a thumbs down" do
@movie.thumbs_down
@movie.rank.should == @initial_rank - 1
end
context "created with a default rank" do
before do
@movie = Movie.new("goonies")
end
it "has a rank of 0" do
@movie.rank.should == 0
end
end
end
$ rspec movie_spec.rb --color --format doc
In the terminal this will show the results with colors and detailed document.
Running all Rspec
$ rspec . --color
Exception handling
Raising An Exception The following is a basic since it will not deal the second error. If you enter 0 twice, it will throw an error.
begin
print("Enter numerator: ")
num = Integer(gets)
print("Enter denominator: ")
denom = Integer(gets)
ratio = num / denom
print(ratio)
rescue
print $! #print error
puts
print("Enter a denominator other than 0: ")
denom = Integer(gets)
ratio = num / denom
print(ratio)
end
begin
print(3/0) # or print(3/1) to show the second error
File.open("myfile.txt")
#rescue ZeroDivisionError
# print("tried to deivide by 0")
# or
rescue ZeroDivisionError => oops
print(oops)
rescue SystemCallError
print("file not found")
end
raise "exception raised" exit the program.
print("In program")
raise "exception raised"
print("Back in program")
# ex 1
def inverse(x)
raise ArgumentError, 'Argument is not numeric' unless x.is_a? Numeric
1.0 / x
end
puts inverse(2)
puts inverse('not a number')
# ex 2
def ctof(temp)
raise ArgumentError, "argument is not numeric" unless temp.is_a? Numeric
return (9.0/5.0) * temp + 32.0
end
puts ctof(4)
puts ctof('not a number')
# ex 3
def ctof(temp)
raise ArgumentError, "argument is not numeric" unless temp.is_a? Numeric
return (9.0/5.0) * temp + 32.0
end
begin
print("Enter a temperature to convert: ")
t = Integer(gets)
print(ctof(t))
rescue
print("Argument was not a number")
end
Catch and throw
alist = [6,1,10,5,9,3,8,4,7,2]
passnum = alist.length-1
catch (:stop) do # catch here
while passnum > 0
for i in 0..passnum-1
print(alist[i])
if i > 6
throw :stop # throwing here
end
end
passnum - 1
end
end
Exercise for exception. list.rb
begin
print("Name of file? :")
name = gets
myFile = File.open(name.chomp)
lines = myFile.read
puts lines
rescue
print("File not found. Enter another name.")
retry # this will take back to 'begin'.
end
Create a file called text.txt.
$ touch text.txt
$ vim text.txt
line 1
line 2
line 3
line 4
:wq!
$ ruby list.rb
IO
Reading a file
readfile.rb
while line = gets
puts line
end
# to read a file
ruby readfile.rb data.txt
Without writing a file name.
File.open("data.txt") do |file|
while line = file.gets
puts line
end
end
$ ruby readfile.rb
Writing a file
writefile.rb
outfile = File.new("myfile.txt","w") # w is for writing
outfile.print("Hello, world\n")
outfile.print("Goodbye, world!")
outfile.close
network
Simple approach for tcp protocl.
client.rb socket
require 'socket' # socket library for tcp
host = 'localhost'
port = 1500
sock = TCPSocket.open(host, port) # open the socket with host and port number.
while line = sock.gets
puts line.chop
end
sock.close
create a server file, server.rb
require 'socket'
server = TCPServer.open(1500) # open the port
loop {
client = server.accept
client.puts("Hello, client!")
client.puts("Goodby, client!")
client.puts("closing connection...")
client.close
}
$ ruby server.rb #first run the server
# open a tab and run a client
$ ruby client.rb
# This will display the content from the server.rb
Reading and writing a data file
Create a text file, temps.txt and add data.
40 38 41 39 43 56
Create a file, tempavg.rb
count = 0
total = 0
while temp = gets
total += Integer(temp)
count += 1
end
puts total / count
Create addtmps.rb
tempfile = File.open("temps.txt","a+") # append to the file
day = 1
while day < 8
print("Enter temperature: ")
temp = gets
tempfile.puts(temp)
day += 1
end
tempfile.close
Run addtemp.rb
$ ruby addtemps.rb
# add number one by one
# check it by open it.
$ cat temps.txt
$ ruby tempavg.rb temps.txt
Ruby debugger
debug1.rb
nums = [1,2,3,4,5]
for i in nums
print (i, i*i)
end
Debug can be done by setting require switch.
$ ruby -r debug debug1.rb # -r means require switch
# This will show the first line.
# By typing l and enter you can list with the whole programe with number lines.
# n and enter shows line by line. And this will show the output in front of debug.
debug2.rb
nums = [5,2,8,3,1,6]
min = 5
for i in nums
if i > min # intentional bug. this is supposed to be if i < min
min = i
end
end
print("The minimum value is ", min)
Start a debugger.
$ ruby -r debug debug2.rb
$ n # to show the next line.
$ disp min # this will display min value
# each time when you disp min, it will add 1,2 etc and display min.
# You just need to do it once.
# by using b 6, it will set a break at 6
Setting a watchpoint
debug3.rb
# fibonacci sequence
t1 = 0
t2 = 1
n = 10
print(0, " ", 1, " ")
while n > 0
t = t1 + t2
print(t, " ")
temp = t2
t2 = t
t1 = temp
n -= 1
end
watchpoint to watch an expression become true.
$ ruby -r debug debug3.rb
$ watch n ==1
Set watchpoint 1:n==1
# program will run until this watchpoint becomes true.
$ c # c to continue
0 1 1 2 3 5 8 13 21 34 55 Watchpoint 1, toplevel at debug3.rb:7
# the program stopped when n==1 and displayed.
$ ruby -r debug debug3.rb
# run for a few times by n
# then type var local
$ var local # to display all variable at that time
# run it again by typing n
$ v l # same as var local
$ quit # to quit debug
debugging exercise
max.rb to practice debugging.
# this will create an infinite loop. It is not increasing pos += 1
nums = [1,3,4,6,2,5]
max = 0
pos = 1
while pos <= nums.length # supposed to be while pos < nums.length
if nums[pos] > nums[max]
max = pos
end
# pos += 1 # through debugging you can uncomment this.
end
print(nums[max])
Graphical use interface Tk
tkexample.rb
require 'tk'
root = TkRoot.new(title "First Example")
TkLabel.new(root) do
text 'A sample GUI using Tk'
pack { padx 15; pady 15; side 'left'}
end
Tk.mainloop
How to install gtk2
I had a problem to install gtk2. This is what I had to do.
cd `brew --prefix`
git fetch origin
git reset --hard origin/master
brew update
brew install glib
brew install gtk+
sudo gem install gtk2