簡単に言えば、次の3行の影響が同じではないのはなぜですか?
if @controller.controller_name == "projects" || @controller.controller_name == "parts"
if @controller.controller_name == ("projects" || "parts")
if @controller.controller_name == "projects" || "parts"
最初のものは私が望む結果を与えてくれますが、実際にはプロジェクトやパーツよりも多くのオプションがあるため、そのフォームを使用すると冗長なステートメントが作成されます。他の2つはよりコンパクトですが、同じ結果は得られません。
||の正確なセマンティクス次のとおりです。
最初の式がうまくいくのは、@controller.controller_name == "projects"
、式は短絡してtrue
を返します。そうでない場合は、2番目の式をチェックします。 2番目と3番目のバリアントは基本的にif @controller.controller_name == "projects"
、以来"projects" || "parts"
等しい"projects"
。あなたはirbでこれを試すことができます:
>> "projects" || "parts"
=> "projects"
あなたがやりたいことは
if ["projects", "parts"].include? @controller.controller_name
違いは何が起こっているかの順序です。 ||も2と3であなたが思っていることをやっていません。
あなたもできる
if ['projects','parts'].include?(@controller.controller_name)
一致するものをさらに追加する必要がある場合に、将来コードを減らすため。
||
もnull合体演算子なので、
"projects" || "parts"
nullではない最初の文字列(この場合は「プロジェクト」)を返します。つまり、2番目の2つの例では、常に評価されます。
if @controller.controller_name == "projects"
Irbを起動すると、これが起こっていることを確認できます。
a = "projects"
b = "parts"
a || b
projects
を返します
そこにはいくつかの異なることがあります:
if @controller.controller_name == "projects" || @controller.controller_name == "parts"
これにより、私が想定しているとおりの動作が得られます。ロジックは非常に基本的です。コントローラー名が「projects」または「parts」の場合、trueを返します
これを行う別の方法は次のとおりです。
if ["projects", "parts", "something else..."].include? @controller.controller_name
これにより、コントローラー名がリスト内のどこかにあるかどうかが確認されます。
次に、他の例について説明します。
if @controller.controller_name == ("projects" || "parts")
これはあなたが望むことをしません。最初に("projects" || "parts")
(「プロジェクト」になります)を評価し、コントローラー名がそれに等しいかどうかのみをチェックします。
if @controller.controller_name == "projects" || "parts"
これはさらに奇妙になります。これは常に真になります。コントローラー名が「プロジェクト」に等しいかどうかを最初にチェックします。その場合、ステートメントはtrueと評価されます。そうでない場合は、それ自体で「パーツ」を評価します。これは、Ruby(ブールロジックの目的上、非nilオブジェクトはすべて「真」と見なされます)で「真」と評価されます)
基本的に、==は他の演算子に分散しません。 3 * (2+1)
が3 * 2 + 3 * 1
と同じ理由は、乗算が加算に分配されるためです。
||の値式はその引数の1つになります。したがって、2番目のステートメントは次と同等です。
if @controller.controller_name == "projects"
||より低い precedence より==なので、3番目のステートメントは次と同等です:
if (@controller.controller_name == "projects") || "ports"
非冗長ソリューションを取得する簡単な方法は
if ["a", "b", "c"].include? x
これは、実際には||
とは関係ありませんが、Rubyで真であると見なされる値は何ですか。すべてがfalseを保存し、nilはtrueです。
論理OR演算子||ブール式で動作するため、文字列で使用しても、望みどおりにはなりません。
あなたが望むものを達成するいくつかの方法があり、それはより冗長で読みやすいです。
Array#includeを使用していますか?そして、簡単なifステートメント:
if ["projects", "parts"].include? @controller.controller_name
do_something
else
do_something_else
end
ケースステートメントの使用:
case @controller.controller_name
when "projects", "parts" then
do_something
else
do_something_else
end
最初に、「projects」および「parts」文字列リテラルを@controller.controller_name
変数と比較します。
2つ目は、「projects」文字列リテラルがfalse
またはnil
でも空の文字列でもないため、「projects」である(「projects」||「parts」)を評価し、@controller.controller_name
と比較します。
3番目は@controller.controller_name
と "projects"を比較し、等しい場合はtrue
を返し、等しくない場合はtrue
ステートメントのif
と等しい "parts"を返します。
多くの人がinclude?
比較を好むようです。
.in?
演算子を使用することを好みます。ずっと簡潔です。また、より読みやすく、arrayに質問をしないため、質問したい変数に質問をします:あなたの場合、controller name。
@controller.controller_name.in? ["projects", "parts"]
または、さらに良い
@controller.controller_name.in? %w[projects parts]