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.
la sémantique exacte de || sont:
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
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.
||
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
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 "))
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"
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.
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
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
.
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]