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


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

Por ejemplo, ¿es esto correcto?

<% question = question.size > 20 ? question.question.slice(0, 20)+"..." : question.question %>
Author: Wayne Conrad, 2010-11-23

7 answers

Es el operador ternario , y funciona como en C (los paréntesis no son necesarios). 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 es también una expresión así: if a then b else c end === a ? b : c, excepto por cuestiones 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 piensa que es puts if 1 con algunos basura extra después de él), pero no se requieren en el último caso como dicha cuestión no se plantea.

Puede usar el formulario" long-if " para legibilidad en varias líneas:

question = if question.size > 20 then
  question.slice(0, 20) + "..."
else 
  question
end
 418
Author: the Tin Man,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-03-09 22:32:28
puts true ? "true" : "false"
=> "true"


puts false ? "true" : "false"
=> "false"
 31
Author: DGM,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2010-11-23 05:04:38

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

<% question = truncate(question, :length=>30) %>
 23
Author: Wayne Conrad,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-10-02 23:16:47

@pst dio una gran respuesta, pero me gustaría mencionar que en Ruby el operador ternario se escribe 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 intentas dividirlo en varias líneas, pero puedes usar el símbolo de continuación de línea \ al final de una línea y Ruby estará feliz:

(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 bien establecido.

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

(true) ?
  1 :
  0

Creo que eso lleva a que sea muy difícil leer el código a medida que la prueba condicional y/o los resultados se hacen más largos.

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


¿Por qué has puesto corchetes true?

Considere el ejemplo de la OP:

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

Envolver la prueba condicional ayuda a hacerla 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 ha sido probado, pero usted tendrá 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 sufre mucho de question.question también.

 16
Author: the Tin Man,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-10-07 17:24:41

Un ejemplo simple donde el operador comprueba si el id del jugador es 1 y establece el id del enemigo dependiendo del resultado

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

Y encontré un post sobre el tema que parece bastante útil.

 3
Author: devwanderer,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-05-29 20:38:50

Una pequeña variación de esto es utilizar el convertir a booleano !! operador como este

result = !!(condition == true)
 0
Author: jcpennypincher,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-12-18 00:06:17

El código condition ? statement_A : statement_B es equivalente a

if condition == true
  statement_A
else
  statement_B
end
 0
Author: Umesh Malhotra,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-09-18 15:13:59