¿Cómo uso el operador condicional (? :) en Ruby?

¿Cómo se usa el operador condicional ( ? : 🙂 En Ruby?

Por ejemplo, ¿es correcto?

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

Es el operador ternario , y funciona como en C (no se requieren los paréntesis). Es una expresión que funciona como:

 if_this_is_a_true_value ? then_the_result_is_this : else_it_is_this 

Sin embargo, en Ruby, if también es una expresión así: if a then b else c end === a ? b : c a ? b : c , excepto por problemas de precedencia. Ambas son expresiones.

Ejemplos:

 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 

Tenga en cuenta que en el primer caso se requieren paréntesis (de lo contrario, Ruby se confunde porque cree que se puts if 1 con algo de basura extra después), pero no son necesarios en el último caso ya que dicho problema no surge.

Puede usar el formulario “long-if” para legibilidad en múltiples líneas:

 question = if question.size > 20 then question.slice(0, 20) + "..." else question end 
 puts true ? "true" : "false" => "true" puts false ? "true" : "false" => "false" 

El uso de ERB sugiere que estás en Rails. Si es así, considere truncate , un ayudante incorporado que hará el trabajo por usted:

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

@pst dio una gran respuesta, pero me gustaría mencionar que en Ruby, el operador ternario está escrito en una línea para ser sintácticamente correcto, a diferencia de Perl y C, donde podemos escribirlo en múltiples líneas:

 (true) ? 1 : 0 

Normalmente, Ruby generará un error si intenta dividirlo en varias líneas, pero puede usar el símbolo \ line-continuation al final de una línea y Ruby estará contento:

 (true) \ ? 1 \ : 0 

Este es un ejemplo simple, pero puede ser muy útil cuando se trata de líneas más largas, ya que mantiene el código muy bien diseñado.

También es posible usar el ternario sin los caracteres de continuación de línea poniendo a los operadores en último lugar en la línea, pero no me gusta o no lo recomiendo:

 (true) ? 1 : 0 

Creo que eso lleva a un código realmente difícil de leer a medida que la prueba condicional y / o los resultados se alargan.

He leído comentarios que dicen que no debe usar el operador ternario porque es confuso, pero esa es una mala razón para no usar algo. Por la misma lógica, no deberíamos usar expresiones regulares, operadores de rango (‘ .. ‘ y la variación de flip-flop aparentemente desconocida). Son poderosos cuando se usan correctamente, por lo que debemos aprender a usarlos correctamente.


¿Por qué has puesto corchetes alrededor de true ?

Considere el ejemplo de OP:

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

Envolver la prueba condicional ayuda a que sea más legible porque separa visualmente la prueba:

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

Por supuesto, todo el ejemplo podría hacerse mucho más legible mediante el uso de algunas adiciones juiciosas de espacios en blanco. Esto no se ha probado pero tendrás la idea:

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

O, más escrito más idiomáticamente:

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

Sería fácil argumentar que la legibilidad también se ve afectada por la question.question .

Un ejemplo simple en el que el operador verifica si la identificación del jugador es 1 y establece la identificación enemiga según el resultado

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

Y encontré una publicación sobre el tema que parece bastante útil.

¡Una pequeña variación de esto es usar la conversión a booleano! operador como este

 result = !!(condition == true)