Forum: Ruby best practice for nested while loops?

Announcement (2017-05-07): www.ruby-forum.com is now read-only since I unfortunately do not have the time to support and maintain the forum any more. Please see rubyonrails.org/community and ruby-lang.org/en/community for other Rails- und Ruby-related community platforms.
0528ea36a904820d78224f5e636066e7?d=identicon&s=25 Soichi Ishida (soujiro0725)
on 2016-08-20 03:04
I am developing a command line tool, that asks users whether to proceed
or not.
It would be...

$ ruby hoge.rb
Proceed? Y/n

If the user enters 'Y', the main action starts.
The main action consists of while loop, in other words, the program
continues itself until it gets interrupted or certain tasks are
completed.

My question is what is the best practice for such programs.
I can write like for instance,

while true
  puts 'Proceed? Y/n'

  if STDIN.gets.chomp == 'Y'
    while true
      # main task
    end
  end

end


But this does not seem readable and smart.
I guess using Thread would help?

Could anyone give me suggestions?
4828d528e2e46f7c8160c336eb332836?d=identicon&s=25 Robert Heiler (shevegen)
on 2016-08-27 01:58
> If the user enters 'Y', the main action starts.
> The main action consists of while loop, in other words, the program
> continues itself until it gets interrupted or certain tasks are
> completed.

> My question is what is the best practice for such programs.
> I can write like for instance,

> while true
>   puts 'Proceed? Y/n'
>
>   if STDIN.gets.chomp == 'Y'
>     while true
>       # main task
>     end
>   end
>
> end

>
> But this does not seem readable and smart.
> I guess using Thread would help?
>
> Could anyone give me suggestions?
>

Well, your above code works. In ruby there is more than one way.

You can use lots of different ways to achieve the above.

I can tell you what I would do - you can then decide whether this
may be applicable to your situation or not.

a) I would write a class. Yes, this may appear so trivial and
overkill, but I write classes all the time in ruby so this has
become second-nature to me.

---

class UserInput

  def initialize
    register_sigint
    run_main_loop
  end
  def run_main_loop
    loop {
      show_default_message
      user_input = $stdin.gets.chomp
      result = check_input_against_menu(user_input)
      break if result == :do_exit
    }
  end
  def register_sigint
    Signal.trap('SIGINT') { exit }
  end
  def check_input_against_menu(i)
    case i
    when 'Y','yes','y'
      puts 'Ok - add here actions'
    when 'N','no','n'
      puts 'ok we exit then.'
      :do_exit
    when 'q','exit'
      :do_exit
    else
      show_default_message
    end
  end
  def show_default_message
    puts 'Proceed? Y/n'
  end
end

UserInput.new

---

The above code should work as-is.

The Signal.trap() part is so that you can use sig-interrupt
to exit, aka Control-C or Shift-C or whatever the key
combination is.

I do not think that you need to use a thread here, because
all you do is query user input, and then do something with
it; use a thread if you want to e. g. batch-download
several files and don't want to pause the main program
as long as these files are downloaded, for instance.

b) of course you could also use two while loops but I don't
think this is necessary. You only need to grab user input
once right? So do it only once, and then correlate this
to the case/when menu of your registered actions, which
ideally should be methods, hence why I use a class.
0528ea36a904820d78224f5e636066e7?d=identicon&s=25 Soichi Ishida (soujiro0725)
on 2016-08-27 02:43
thanks helps a lot!
0fa73332c8e4a3b06ea439fd3f034322?d=identicon&s=25 Ronald Fischer (rovf)
on 2016-08-29 17:38
def confirm
  puts 'Proceed? Y/n'
  STDIN.gets.chomp == 'Y'
end

while confirm
  do_main_task
end
This topic is locked and can not be replied to.