web-dev-qa-db-fra.com

Comprendre le "||" OR opérateur dans If conditionals dans Ruby

Brièvement, pourquoi les trois lignes suivantes ne sont-elles pas identiques dans leur impact?

if @controller.controller_name == "projects" || @controller.controller_name == "parts"

if @controller.controller_name == ("projects" || "parts")

if @controller.controller_name == "projects" || "parts"

Le premier me donne le résultat que je veux, mais comme il y a en fait plus d'options que des projets et des pièces, l'utilisation de ce formulaire crée une déclaration détaillée. Les deux autres sont plus compacts, mais ne me donnent pas le même résultat.

34
steven_noble

la sémantique exacte de || sont:

  • si la première expression n'est pas nulle ou fausse, retournez-la
  • si la première expression est nulle ou fausse, retourne la deuxième expression

donc à quoi sert votre première expression, si @controller.controller_name == "projects", puis l'expression court-circuite et renvoie true. sinon, il vérifie la deuxième expression. les deuxième et troisième variantes sont essentiellement if @controller.controller_name == "projects", puisque "projects" || "parts" équivaut à "projects". vous pouvez essayer ceci dans irb:

>> "projects" || "parts"
=> "projects"

ce que tu veux faire c'est

if ["projects", "parts"].include? @controller.controller_name
56
Martin DeMello

La différence est l'ordre de ce qui se passe. Aussi le || ne fait pas ce que vous pensez qu'il fait dans les 2 et 3.

Vous pouvez aussi faire

if ['projects','parts'].include?(@controller.controller_name)

pour réduire le code à l'avenir si vous devez ajouter plus de correspondances.

7
Jim

|| est également un opérateur de coalescence nul, donc

"projects" || "parts"

retournera la première chaîne qui n'est pas nulle (dans ce cas "projets"), ce qui signifie que dans les deux seconds exemples, vous évaluerez toujours:

if @controller.controller_name == "projects"

En tirant irb, vous pouvez vérifier que cela se produit:

a = "projects"
b = "parts"

a || b

renvoie projects

6
jerhinesmith

Il se passe plusieurs choses différentes:

if @controller.controller_name == "projects" || @controller.controller_name == "parts"

cela donne le comportement que vous voulez, je suppose. La logique est assez basique: retourne vrai si le nom du contrôleur est "projets" ou "parties"

Une autre façon de procéder est:

if ["projects", "parts", "something else..."].include? @controller.controller_name

Cela vérifiera si le nom du contrôleur est quelque part dans la liste.

Maintenant, pour les autres exemples:

if @controller.controller_name == ("projects" || "parts")

Cela ne fera pas ce que vous voulez. Il évaluera ("projects" || "parts") d'abord (ce qui entraînera des "projets"), et ne vérifiera ensuite que si le nom du contrôleur est égal à celui-ci.

if @controller.controller_name == "projects" || "parts"

Celui-ci devient encore plus farfelu. Cela se traduira toujours par vrai. Il vérifiera d'abord si le nom du contrôleur est égal à "projets". Si tel est le cas, l'instruction prend la valeur true. Sinon, il évalue les "parties" par lui-même: ce qui est également évalué à "vrai" dans Ruby (tout objet non nul est considéré comme "vrai" aux fins de la logique booléenne "))

4
madlep

Fondamentalement, == ne se distribue pas sur les autres opérateurs. La raison pour laquelle 3 * (2+1) est identique à 3 * 2 + 3 * 1 est que la multiplication se répartit sur l'addition.

La valeur d'un || expression sera l'un de ses arguments. Ainsi la 2ème déclaration équivaut à:

if @controller.controller_name == "projects"

|| est inférieur précédence que ==, donc la 3ème instruction est équivalente à:

if (@controller.controller_name == "projects") || "ports"
3
outis

La manière simple d'obtenir une solution non verbeuse est

if ["a", "b", "c"].include? x

Cela n'a rien à voir avec ||, mais plutôt quelles valeurs sont considérées comme vraies dans Ruby. Tout sauf faux et nul est vrai.

2
Logan Capaldo

L'opérateur logique ou || fonctionne sur les expressions booléennes, donc l'utiliser sur des chaînes ne fait pas ce que vous voulez.

Il existe plusieurs façons de réaliser ce que vous voulez qui sont moins verbeuses et plus lisibles.

L'utilisation de Array # include? et une simple instruction if:

if ["projects", "parts"].include? @controller.controller_name
  do_something
else
  do_something_else
end

Utilisation d'une déclaration de cas:

case @controller.controller_name
when "projects", "parts" then
  do_something
else
  do_something_else
end
1
Lars Haugseth

Le premier compare les littéraux de chaîne "projets" et "pièces" à @controller.controller_name variable.

Le second évalue ("projets" || "pièces") qui est "projets" car "projets" littéral de chaîne ni false ou nil ou chaîne vide et le compare à @controller.controller_name

Le troisième compare @controller.controller_name et "projets" et s'ils sont égaux, il renvoie true, s'ils ne le sont pas, retourne "parts" qui est égal à true pour l'instruction if.

0
vava

Je vois beaucoup de gens préférer le include? Comparaison.

Je préfère utiliser le .in? opérateur. C'est beaucoup plus succinct. Et aussi plus lisible, puisque nous ne posons pas de questions au tablea, nous posons des questions à la variable que vous souhaitez poser: Dans votre cas, le nom du contrôleur.

@controller.controller_name.in? ["projects", "parts"]

Ou encore mieux

@controller.controller_name.in? %w[projects parts]
0
Victor