I have a simple ruby script I would like to run in the rails console, using bundle exec rails c
ids = [1, 2]
if ids.length() > 5
puts "More than 5 ids, quitting"
exit
end
ids.each do |id|
puts id
end
The rails console quits the program as soon as it sees the exit command. What would be the best way around this?
CodePudding user response:
One way to do this is to use throw/catch
:
ids = [1, 2]
catch(:bail) do
if ids.length > 5
puts "More than 5 ids, quitting"
throw :bail
end
ids.each do |id|
puts id
end
end
catch :bail
defines a block that is labeled with the symbol :bail
(the name doesn't really matter). It will execute normally until you throw :bail
at which point Ruby zips up the call stack until its finds a corresponding catch. If no matching catch is found an UncaughtThrowError will be raised.
This is somewhat like break
but can be used in any context and to break out of deeply nested constructs.
Another alternative would be to simply define a method or raise (and rescue) an exception if the input is invalid.
CodePudding user response:
Raise ArgumentError When Passed Arguments are Somehow Invalid
There are a lot of ways to fix your code, but your essential problem is that Kernel#exit will exit both a standard REPL session and an application, not simply return from a method or break out of an if-statement. Since your code doesn't show that you're inside a method, you can't use return
because there's no appropriate method or closure to return from. You could possibly work around calling #exit with nested irb sessions or the like, but that's ultimately solving the wrong problem.
In most cases, you want to raise an exception with a useful message rather than simply exit when something goes unfixably wrong. The following would do that in your application, while in an irb or pry console it will raise the exception but remain within your REPL session:
ids = [1, 2]
raise ArgumentError, "More than 5 ids: #{ids}" if ids.length > 5
ids.each { |id| puts id }
If you were inside a method, you could use #warn and then return an appropriate return value instead. However, since you are presumably inside the top-level object of your REPL, there's nothing to return from, so this is likely your best general-purpose option.