#ruby #console #irb
Вопрос:
У меня есть простой скрипт ruby, который я хотел бы запустить в консоли rails, используя bundle exec rails c
ids = [1, 2] if ids.length() gt; 5 puts "More than 5 ids, quitting" exit end ids.each do |id| puts id end
Консоль rails завершает работу программы, как только видит команду выхода. Как бы лучше всего это обойти?
Комментарии:
1. Не ставить
exit
?2.
exit
указывает процессу Ruby на выход. Что вы ожидали от этого?3. Извините, я отредактировал первый цикл, чтобы было понятнее
4. Ну, этот код на самом деле не выполняется. В качестве альтернативы, вместо
exit
этого вы можете установить флаг (dont_run = true
или что-то в этом роде) и завернуть код, который вы хотите пропустить, в проверку этого флага.5. @SergioTulentsev Да. Еще лучше: поместите его в метод, который возвращает или выдает ошибку при выполнении с недопустимыми параметрами. Таким образом, автор может вызвать метод из консоли Ruby. Возможно, именно этого и хотел автор.
Ответ №1:
Один из способов сделать это-использовать throw/catch
:
ids = [1, 2] catch(:bail) do if ids.length gt; 5 puts "More than 5 ids, quitting" throw :bail end ids.each do |id| puts id end end
catch :bail
определяет блок, помеченный символом :bail
(название на самом деле не имеет значения). Он будет выполняться нормально до тех пор, пока вы throw :bail
, и в этот момент Ruby не закроет стек вызовов, пока не найдет соответствующий улов. Если соответствующий улов не найден, будет поднята ошибка «Не пойман».
Это чем-то похоже break
, но может быть использовано в любом контексте и для выхода из глубоко вложенных конструкций.
Другой альтернативой было бы просто определить метод или вызвать (и спасти) исключение, если ввод неверен.
Ответ №2:
Поднимите аргумент, если переданные Аргументы Каким-либо образом недействительны
Существует множество способов исправить ваш код, но ваша основная проблема заключается в том, что Kernel#exit завершит как стандартный сеанс REPL, так и приложение, а не просто вернется из метода или выйдет из оператора if. Поскольку ваш код не показывает, что вы находитесь внутри метода, вы не можете его использовать return
, потому что нет подходящего метода или закрытия для возврата. Возможно, вы могли бы обойти вызов #exit с вложенными сеансами irb или чем-то подобным, но это в конечном итоге решает неправильную проблему.
В большинстве случаев вы хотите создать исключение с полезным сообщением, а не просто выйти, когда что-то пойдет не так. Следующее сделает это в вашем приложении, в то время как в консоли irb или pry это вызовет исключение, но останется в вашем сеансе REPL:
ids = [1, 2] raise ArgumentError, "More than 5 ids: #{ids}" if ids.length gt; 5 ids.each { |id| puts id }
Если бы вы находились внутри метода, вы могли бы использовать #warn, а затем вместо этого вернуть соответствующее возвращаемое значение. Однако, поскольку вы, предположительно, находитесь внутри объекта верхнего уровня вашего REPL, возвращаться не из чего, так что, вероятно, это ваш лучший вариант общего назначения.