Как использовать условный оператор (?:) в Ruby?

Как используется условный оператор (? :) в Ruby?

Например, это правильно?

<% question = question.size > 20 ? question.question.slice(0, 20)+"..." : question.question %>

Ответ 1

Это тернарный оператор, и он работает как в C (скобки не требуются). Это выражение, которое работает как:

if_this_is_a_true_value ? then_the_result_is_this : else_it_is_this

Однако, в Ruby, if также является выражением so: if a then b else c end === a ? b : c, за исключением проблем с приоритетом. Оба являются выражениями.

Примеры:

puts (if 1 then 2 else 3 end) # => 2

puts 1 ? 2 : 3                # => 2

x = if 1 then 2 else 3 end
puts x                        # => 2

Обратите внимание, что в первом случае требуются скобки (в противном случае Ruby запутан, потому что он считает, что это puts if 1 с некоторым дополнительным нежелательным результатом после него), но они не требуются в последнем случае, поскольку указанная проблема не возникает.

Вы можете использовать форму "long-if" для чтения на нескольких строках:

question = if question.size > 20 then
  question.slice(0, 20) + "..."
else 
  question
end

Ответ 2

puts true ? "true" : "false"
=> "true"


puts false ? "true" : "false"
=> "false"

Ответ 3

Ваше использование ERB предполагает, что вы находитесь в Rails. Если да, тогда рассмотрите truncate, встроенный помощник, который выполнит эту работу для вас:

<% question = truncate(question, :length=>30) %>

Ответ 4

@pst дал отличный ответ, но я хотел бы упомянуть, что в Ruby тернарный оператор написан на одной строке синтаксически корректным, в отличие от Perl и C, где мы можем записать его на несколько строк:

(true) ? 1 : 0

Обычно Ruby будет вызывать ошибку, если вы попытаетесь разбить ее на несколько строк, но вы можете использовать символ продолжения строки \ в конце строки, и Ruby будет счастлив:

(true)   \
  ? 1    \
  : 0

Это простой пример, но он может быть очень полезен при работе с более длинными строками, поскольку он хорошо сохраняет код.

Также возможно использовать тернар без символов продолжения строки, помещая операторы в строку, но мне это не нравится или рекомендую:

(true) ?
  1 :
  0

Я думаю, что это приводит к тому, что очень трудно читать код, поскольку условный тест и/или результаты становятся длиннее.

Я читал комментарии, говорящие, что не использовать тернарный оператор, потому что он запутывает, но это плохая причина не использовать что-то. По той же логике мы не должны использовать регулярные выражения, операторы дальности ('..' и, по-видимому, неизвестную вариацию "триггера" ). Они эффективны при правильном использовании, поэтому мы должны научиться правильно их использовать.


Почему вы помещаете скобки вокруг true?

Рассмотрим пример OP:

<% question = question.size > 20 ? question.question.slice(0, 20)+"..." : question.question %>

Обертка условного теста помогает сделать его более читаемым, поскольку он визуально отделяет тест:

<% question = (question.size > 20) ? question.question.slice(0, 20)+"..." : question.question %>

Конечно, весь пример можно было бы сделать более читаемым, используя некоторые разумные добавления пробелов. Это непроверено, но вы получите идею:

<% question = (question.size > 20) ? question.question.slice(0, 20) + "..." \
                                   : question.question 
%>

Или более написано более идиоматично:

<% question = if (question.size > 20)
                question.question.slice(0, 20) + "..."
              else 
                question.question 
              end
%>

Было бы легко аргументировать, что читаемость плохо страдает и от question.question.

Ответ 5

Простой пример, в котором оператор проверяет, равен ли id игрока 1 и устанавливает идентификатор противника в зависимости от результата

player_id=1
....
player_id==1? enemy_id=2 : enemy_id=1
# => enemy=2

И я нашел post о теме, которая кажется весьма полезной.

Ответ 6

Один маленький вариант заключается в том, чтобы использовать преобразование в boolean!! такой оператор

result = !!(condition == true)