Re-open a script in ruby - ruby

I would like to re-open my script at the end of its execution. I tried with load but it didn't work. Is what I want to do possible? If yes, what should I try?
This is the structure of my script:
usr_choice = gets.chomp.to_i
case usr_choice
when 1
# Do something
when 2
# Do something else
else
puts "Choice not recognised"
end
Basically I would like for example to go back to the user input (usr_choice) after going through the case statement. Without a GoTo.

So you want a loop? Well, use loop:
loop do
usr_choice = gets.chomp.to_i
case usr_choice
when 1
puts 'one'
when 2
puts 'two'
else
break # exit the loop (not the case construct as in other languages)
end
end
Example:
$ ruby filename.rb
1
one
2
two
1
one
kthxbye
$

Related

Why the global variable not works in .rb file but works in irb?

I was trying to add indentation based on how deep the block goes. I used a global variable to record the depth of block.
$depth = 0
def log(des, &block)
indentation = " " * $depth
$depth += 1
puts "#{indentation}Begginning the #{des} block"
puts "#{indentation}Finished #{des} and returned: #{block.call}"
$depth -= 1
end
log "outer block" do
log "second level block" do
log "third level block" do
"I am number 3"
end
"I am number 2"
end
"I am out most!"
end
In terminal I tried several times ruby file_name.rb, it showed no indentation, it even won't puts the global variable out. After then I copy the code to irb and it worked.
Why this happened?
What's the difference when running ruby code in between these two places?
I suspect you have a different definition of log() in your environment. Changing the name of your routine to something else (say 'mylog') will test this hypothesis.

How to write a case statement in Ruby with multiple statements inside a when clause?

I tried separating the statements inside the when clauses with commas but it didn't work.
when 1; statement, statement, statement
when 2; statement, statement, statement
I couldn't find any examples of this online.
case selection
when 1
system "clear"
view_all_entries
main_menu
when 2
system "clear"
create_entry
main_menu
when 3
system "clear"
search_entries
main_menu
when 5
puts "Good bye!"
exit(0)
else
system "clear"
puts "Sorry, that is not a valid input"
main_menu
end
Your question seems to be "how can I put all those statements on one line to have fewer lines".
Generally, you can use ";" in ruby to replace the End-of-Lines. Thus:
case selection
when 1; system "clear"; view_all_entries; main_menu
...
Or
case selection
when 1 then system "clear"; view_all_entries; main_menu
...
Using the ";" in any way is very much not ruby-like and not recommended. See below for a much nicer refactoring which strips the duplicated code.
I would be inclined to write it thusly:
if selection==5
puts "Good bye!"
exit(0)
end
system "clear"
case selection
when 1 then view_all_entries
when 2 then create_entry
when 3 then search_entries
else puts "Sorry, that is not a valid input"
end
main_menu
i've tried comma, it does not work
Yes, it does:
case value
when 1, 2
"one or two"
else
"something other than one or two"
end
returns "one or two" if value is 1 or 2
You can use the when - then syntax. Note that it is considered bad practice if the lines become too long:
case value
when 1 then statement1
when 2 then statement2
when 3 then statement3
when 4 then statement4
end
To execute multiple statements for the same condition on the same line you can separate them with ;. However, this is always considered a bad practice:
case value
when 1 then statement1; statement11; statement12
when 2 then statement2; statement21; statement22
when 3 then statement3; statement31; statement32
when 4 then statement4; statement41; statement42
end

How to run a simple Ruby script

I would like to make a program that checks to see if the number you enter is an even number. Sort of like making a leap year program but for any number divisible by 2.
Something along the lines of:
num = gets.chomp
while num != 0
if (num%2) == 0
puts 'yess'
else
puts 'nooo'
end
end
I knows there's something easy that I need to change for it to run.
(btw I just started learning Ruby yesterday!)
There are two problems here.
First being something that others have put, you need to make sure you turn the input into an integer using ".to_i" on your num variable.
Secondly, this code puts you into an infinite loop since you are using a "while" loop.
Since the number is only input once, you get stuck in the "while" loop forever no matter what the input is. Basically, "num" never stops being not 0.
You'd be better off using an if..else statement. Something like:
num = gets.chomp.to_i
if num != 0
if (num%2) == 0
puts 'yess'
else
puts 'nooo'
end
else
puts "that's 0, dude"
end
Integers have two methods for this. They are even? and odd?.
You can use this in your if statement as so:
if num.even?
puts 'yess'
else
puts 'nooo'
end
However, an easier way to write this is with ternary expressions:
puts num.even? ? "yes" : "no"
However, make sure num is an Integer. Anything coming from gets will be a String. So, you should be doing num = gets.chomp.to_i. Anything that is not a number, like "h", will return 0.
"5".to_i #=> 5
"h".to_i #=> 0

Program not entering in if-else block in Ruby

If i give input as 1 or 2, regardless of that program goes in default. Tried comparing input with "1" and 1 both. Same result.
My first Ruby program, plz excuse for naivety.
$choice
def getInfo
puts "Info"
end
def getMoreInfo
puts "MoreInfo"
end
def switch
if $choice == "1" #intentionally in ""
getInfo
elsif $choice == 2 #intentionally without ""
getMoreInfo
else
puts "default"
end
end
def callMainMenu
puts "Choose the operation:"
puts "[1] Get some Info"
puts "[2] Get some moreInfo"
$choice=gets
$choice.chomp
end
callMainMenu
switch
You need to use the destructive version of chomp if you're going to assign it like that.
$choice.chomp!
Or
$choice = $choice.chomp
In order to debug this, what I'd do is add puts $choice.inspect at the beginning of your switch method to see exactly what's in the variable. That said, I believe the problem here is that you're calling $choice.chomp instead of $choice.chomp!. The former will return the result, and the latter will change the variable in place.
When you change $choice.chomp to $choice.chomp! and get rid of the // (change those to #), then you'll have something working. Keep refining it , it is not perfect yet.
Use $choice.chomp!. chomp without ! does not alter $choice. It returns a new string. This a naming convention in Ruby.

ruby - How to return from inside eval?

I have a code which I need to use within eval. Sometimes I need to get out from the eval code, but my tries lead to errors.
E.g.:
# expected to see 1, 2 and 5; not 3 nor 4; and no errors
eval "puts 1; puts 2; return; puts 3; puts 4" # => Error: unexpected return
puts 5
I tried with return, end, exit, break, and I couldn't get success. exit doesn't raise errors, but then I don't get the 5.
(Note: I know that eval is evil, but in this case I need to use it.)
Thank you all, but I found a solution which fits best into my problem:
lambda do
eval "puts 1; puts 2; return; puts 3; puts 4"
end.call
puts 5
This way the intuitive return keyword can be used inside eval to get out from it successfully.
I didn't like the conditional-like solutions in this case because it would force me (or the user) to add an end at the end.
About using throw/catch or break, I consider the return keyword more intuitive.
eval'd code is just being run in this place. It's not a function or block. How would you do it without eval? Probably like this:
puts 1
puts 2
if(conditionFor3And4)
puts 3
puts 4
end
you Can't. You can return out of methods, and break out of blocks or loops, but not eval.
You could try a throw/catch block instead
eval "
should_stop = true
catch :stop do
puts 1
puts 2
throw :stop if should_stop
puts 3
end
"
or this:
should_stop = true
catch :stop do
eval "
puts 1
puts 2
throw :stop if should_stop
puts 3
"
end
or just do a conditional like Mchl said, since you probably want it to conditional stop, not just always, but throw catch will let you jump out of a block no matter how many levels down you are, which make it more robust, if you need to break out of a nested loop or something like that.
You could just use conditionals instead of early returns.
You could quite happily define a function and execute it last at the end of the script as follows:
def ev(s)
eval("def doStuff()\n" + s + "\nend\ndoStuff()")
end
ev("
1
return 2
3
")
#=> 2
Demo

Resources