В коде, который я пытался исправить сегодня, был такой восхитительный фрагмент:

def needs_update?
  bundle_command('check')   
  $? != 0
end

Итак, давайте пойдем «ля-ля-ля» и проигнорируем зависимость от глобальной системной переменной $?.

Цель состоит в том, чтобы использовать возвращаемое значение системной команды (бандлера) для возврата логического значения из метода. Документ для команды (проверка пакета) говорит

Check ищет на локальном компьютере каждый из драгоценных камней, запрошенных в Gemfile. Если все драгоценные камни найдены, Bundler печатает сообщение об успешном выполнении и завершает работу со статусом 0. Если нет, отображается первый отсутствующий драгоценный камень, и Bundler выходит из состояния 1.

Чего он не говорит, так это того, что когда вы пытаетесь выполнить команду и что-то мешает этому, UNIX возвращает ненулевой код состояния, поэтому, если что-то еще не так, needs_update? всегда кажется верным.

Вернемся к этому $?. Как оказалось, это экземпляр ruby ​​System::Status, а не числовое значение, которое вы получили бы от bash. Так что это тоже никогда не будет нулем. $?.exitstatus может быть тем, что нам нужно.

Таким образом, приведенный выше метод всегда возвращает true, и когда остальная часть системы работает, он без необходимости запускает установку пакета. А когда что-то ломается, он пытается и молча терпит неудачу.

  1. Что я всегда неправильно понимаю, так это то, почему люди не думают двойным отрицанием? …или
  2. Почему люди думают двойным отрицанием?

В документе говорится, что если проверка пакета возвращает 1, нам нужно выполнить установку драгоценного камня. Итак, давайте проверим наличие положительного индикатора ожидаемого состояния. Итак, $?.exitstatus == 1, верно?

Итак, теперь, когда я начал, какого черта: методы могут возвращать значения (я знаю, типа… кто знал?).

Так почему бы этому методу bundle_command не управлять своими внутренними компонентами и не возвращать что-то полезное. Возможно, он мог бы вернуть целое число статуса выхода.

Но, эй, если мы имеем дело с Bundler в классе (а так оно и есть), почему бы не скрыть внутренности бандлера от бедняги (меня), который должен был это выяснить, и сделать мне хороший метод bundle_needs_update?, который возвращает true или false . Если он не получит два задокументированных кода возврата, он должен вызвать исключение. У нас все еще мог бы быть метод bundle_command(command_name), который возвращает что-то подходящее, и просто иметь симпатичную маленькую оболочку.

Это только я? Разве в школах не преподают эти действительно базовые концепции программирования?