Как используется условный оператор (? :
) в Ruby?
Например, это правильно?
<% question = question.size > 20 ? question.question.slice(0, 20)+"..." : question.question %>
Как используется условный оператор (? :
) в Ruby?
Например, это правильно?
<% question = question.size > 20 ? question.question.slice(0, 20)+"..." : question.question %>
Это тернарный оператор, и он работает как в 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
puts true ? "true" : "false"
=> "true"
puts false ? "true" : "false"
=> "false"
Ваше использование ERB предполагает, что вы находитесь в Rails. Если да, тогда рассмотрите truncate
, встроенный помощник, который выполнит эту работу для вас:
<% question = truncate(question, :length=>30) %>
@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
.
Простой пример, в котором оператор проверяет, равен ли id игрока 1 и устанавливает идентификатор противника в зависимости от результата
player_id=1
....
player_id==1? enemy_id=2 : enemy_id=1
# => enemy=2
И я нашел post о теме, которая кажется весьма полезной.
Один маленький вариант заключается в том, чтобы использовать преобразование в boolean!! такой оператор
result = !!(condition == true)