web-dev-qa-db-fra.com

Comment utiliser l'opérateur conditionnel (? :) dans Ruby?

Comment l'opérateur conditionnel (? :) est-il utilisé dans Ruby?

Par exemple, est-ce correct?

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

Il s’agit de l’opérateur ternary , et il fonctionne comme en C (les parenthèses ne sont pas obligatoires). C'est une expression qui fonctionne comme:

if_this_is_a_true_value ? then_the_result_is_this : else_it_is_this

Cependant, en Ruby, if est également une expression: if a then b else c end === a ? b : c, sauf en ce qui concerne les problèmes de priorité. Les deux sont des expressions.

Exemples:

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

Notez que dans le premier cas, les parenthèses sont obligatoires (sinon, Ruby est confus car il pense que c’est puts if 1 suivi de jonques supplémentaires), mais elles ne sont pas obligatoires dans le dernier cas car le problème ne se pose pas.

Vous pouvez utiliser le formulaire "long-if" pour la lisibilité sur plusieurs lignes:

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


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

Votre utilisation de ERB suggère que vous êtes dans Rails. Si tel est le cas, considérez truncate , un assistant intégré qui fera le travail pour vous:

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

@pst a donné une bonne réponse, mais je voudrais mentionner qu'en Ruby l'opérateur ternaire est écrit sur une ligne pour être syntaxiquement correct, contrairement à Perl et C où nous pouvons l'écrire sur plusieurs lignes:

(true) ? 1 : 0

Normalement, Ruby générera une erreur si vous essayez de la scinder sur plusieurs lignes. Vous pouvez toutefois utiliser le symbole \ continuation de la ligne à la fin d'une ligne pour que Ruby soit satisfait:

(true)   \
  ? 1    \
  : 0

Ceci est un exemple simple, mais il peut s'avérer très utile pour traiter des lignes plus longues car le code reste bien agencé.

Il est également possible d'utiliser le caractère ternaire sans les caractères de continuation de ligne en plaçant les opérateurs en dernier sur la ligne, mais je n'aime ni ne le recommande:

(true) ?
  1 :
  0

Je pense que cela rend la lecture du code très difficile car le test conditionnel et/ou les résultats s'allongent.

J'ai lu des commentaires qui disaient de ne pas utiliser l'opérateur ternaire parce que c'était déroutant, mais c'est une mauvaise raison de ne pas utiliser quelque chose. Dans la même logique, nous ne devrions pas utiliser d'expressions régulières, d'opérateurs d'intervalle ('..' et la variation apparemment inconnue de «bascule»). Ils sont puissants lorsqu'ils sont utilisés correctement, nous devrions donc apprendre à les utiliser correctement.


Pourquoi avez-vous mis des parenthèses autour de true?

Prenons l'exemple du PO:

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

Envelopper le test conditionnel contribue à le rendre plus lisible, car il sépare visuellement le test:

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

Bien sûr, l’exemple tout entier pourrait être rendu beaucoup plus lisible en ajoutant judicieusement des espaces. Ceci n’a pas été testé, mais vous aurez l’idée:

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

Ou, plus écrit plus idiomatiquement:

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

Il serait facile d'argumenter que la lisibilité souffre également de question.question.

17
the Tin Man

Un exemple simple où l'opérateur vérifie si l'identifiant du joueur est 1 et définit l'identifiant de l'ennemi en fonction du résultat

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

Et j'ai trouvé un post sur le sujet qui semble très utile.

3
devwanderer

Une petite variante de ceci est d'utiliser le converti en boolean !! opérateur comme ça

result = !!(condition == true)
0
jcpennypincher

Le code condition ? statement_A : statement_B est équivalent à 

if condition == true
  statement_A
else
  statement_B
end
0
Umesh Malhotra