Understanding the || OR operator in If conditionals in Ruby
the exact semantics of || are:
- if first expression is not nil or false, return it
- if first expression is nil or false, return the second expression
so what your first expression works out to is, if @controller.controller_name == "projects"
, then the expression short-circuits and returns true
. if not, it checks the second expression. the second and third variants are essentially if @controller.controller_name == "projects"
, since "projects" || "parts"
equals "projects"
. you can try this in irb:
>> "projects" || "parts"
=> "projects"
what you want to do is
if ["projects", "parts"].include? @controller.controller_name
Difference between or and || in Ruby?
It's a matter of operator precedence.
||
has a higher precedence than or
.
So, in between the two you have other operators including ternary (? :
) and assignment (=
) so which one you choose can affect the outcome of statements.
Here's a ruby operator precedence table.
See this question for another example using and
/&&
.
Also, be aware of some nasty things that could happen:
a = false || true #=> true
a #=> true
a = false or true #=> true
a #=> false
Both of the previous two statements evaluate to true
, but the second sets a
to false
since =
precedence is lower than ||
but higher than or
.
Logic OR / AND term evaluation order in Ruby
Ruby community commonly used is short-circuit
evaluation which is &&
stands for AND
, ||
stands for OR
It means in a conditional statement with two conditions the second condition is evaluated only when the first condition is not enough to determine the value of expression
so let's take an example for &&
, ||
def a
puts 'a method'
false
end
def b
'b method'
true
end
a && b
# 'a method'
# => false
b is never evaluated
def a
puts 'a method'
true
end
def b
'b method'
false
end
a || b
# 'a method'
# => true
b is also never evaluated
there is another construction and
, or
(lowercased)
The and and or keywords serve the same purpose in Ruby. Properly understood, and and or are control flow operators, not boolean operators.
You use them as more like control-flow operators if
, unless
. This operations have very low operator precedence.
Further reading:
and or and short-curcuit difference
short-curcuit
What does ||= (or-equals) mean in Ruby?
This question has been discussed so often on the Ruby mailing-lists and Ruby blogs that there are now even threads on the Ruby mailing-list whose only purpose is to collect links to all the other threads on the Ruby mailing-list that discuss this issue.
Here's one: The definitive list of ||= (OR Equal) threads and pages
If you really want to know what is going on, take a look at Section 11.4.2.3 "Abbreviated assignments" of the Ruby Language Draft Specification.
As a first approximation,
a ||= b
is equivalent to
a || a = b
and not equivalent to
a = a || b
However, that is only a first approximation, especially if a
is undefined. The semantics also differ depending on whether it is a simple variable assignment, a method assignment or an indexing assignment:
a ||= b
a.c ||= b
a[c] ||= b
are all treated differently.
Ruby unless conditional with || operator
Unless
is the exact opposite of If
. It’s a negated If
.
Unless
will work when the condition is false
2.3.4 :010 > unless false || false
2.3.4 :011?> puts "unless block"
2.3.4 :012?> end
unless block
=> nil
So by this or condition ||
result is false
when both sides are false
2.3.4 :019 > false || false
=> false
else the result is always true
below code will not execute the puts statement because the condition gives true
2.3.4 :022 > unless false || true
2.3.4 :023?> puts "unless block"
2.3.4 :024?> end
=> nil
2.3.4 :019 > false || true
=> true
And your &&
is worked because it gives false
when execute below stmt and unless
worked with false :-
2.3.4 :019 > false && true
=> false
For more here is a reference https://mixandgo.com/learn/if-vs-unless-in-ruby
How do I use the conditional operator (? :) in Ruby?
It is the ternary operator, and it works like in C (the parenthesis are not required). It's an expression that works like:
if_this_is_a_true_value ? then_the_result_is_this : else_it_is_this
However, in Ruby, if
is also an expression so: if a then b else c end
=== a ? b : c
, except for precedence issues. Both are expressions.
Examples:
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
Note that in the first case parenthesis are required (otherwise Ruby is confused because it thinks it is puts if 1
with some extra junk after it), but they are not required in the last case as said issue does not arise.
You can use the "long-if" form for readability on multiple lines:
question = if question.size > 20 then
question.slice(0, 20) + "..."
else
question
end
Ruby Syntax - What is the difference between (? and if else)
This is the ternary operator that has been a staple of languages for a long time. My believe is it's inclusion in Ruby was in an effort to ease the transition to Ruby from other languages for developers.
It essentially reads
<condition>
? <result if true>
: <result if false>
Its use primarily lies in those instances you have a simple condition with only two possible simple outcomes. It steamlines the if/else block into a single line. It is not quite as readable as an inline if statement.
The example statement: @date = params[:month] ? Date.parse(params[:month]) : Date.today
Essentially breaks down into an assignment, condition, and true and false values.
And effectively does this:
- assignment:
@date =
- set date to the value returned by the ternary statement - condition:
params[:month]
- a month value - note: nil evaluates to false when used in a condition. - true value:
Date.parse(params[:month])
- Parse the month value as a date. - false value:
Date.today
- default value used if there is no date.
In more longer form ruby this essentially does this (the condition is not the same, because it is calling out the explicit case inferred from the statement, i.e.: the one most likely to trigger the false case).
if ! params[:month].nil?
@date = Date.today
else
@date = Date.parse(params[:month])
end
As for your comment about question marks in method names, that is a convention that allows a developer to distinguish methods that a return a boolean quickly from other methods. Just like methods that end with an exclamation point indicate methods that modify their caller.
The syntax difference is in the space between the method name and the operator.
Whereas most infix operators can be used without spaces, between the first and second operators, the ternary operator requires a space, between the first argument (condition) and the question mark, because the question mark can be a valid part of a method or variable name.
What is the difference between if statements with then at the end?
then
is a delimiter to help Ruby identify the condition and the true-part of the expression.
if
condition then
true-part else
false-part end
then
is optional unless you want to write an if
expression in one line. For an if-else-end spanning multiple lines the newline acts as a delimiter to split the conditional from the true-part
# can't use newline as delimiter, need keywords
puts if (val == 1) then '1' else 'Not 1' end
# can use newline as delimiter
puts if (val == 1)
'1'
else
'Not 1'
end
Why does single `=` work in `if` statement?
The only necessary thing for an if
statement to be valid is a boolean expression. In this case, since =
returns the result of the assignment, what's actually being tested is the falsiness of session["devise.facebook_data"]
.
IntelliJ has a good point to lodge a complaint about code like this, as it's difficult to read without knowing a thing or two about Ruby. A recommendation would be to move that to an explicit assignment statement instead. This has the added benefit of DRYing up a reference to it twice.
class User < ActiveRecord::Base
def self.new_with_session(params, session)
super.tap do |user|
data = session["devise.facebook_data"]
if data && data["extra"]["raw_info"]
user.email = data["email"] if user.email.blank?
end
end
end
end
Related Topics
Best Practices With Stdin in Ruby
How to Modify Path For Homebrew
How to Get Source Code of a Method Dynamically and Also Which File Is This Method Locate In
Ruby Operator Precedence Table
Confusion With the Assignment Operation Inside a Falsy 'If' Block
Rails :Dependent =≫ :Destroy VS :Dependent =≫ :Delete_All
No Such File to Load - Rubygems (Loaderror)
Your Ruby Version Is 2.0.0, But Your Gemfile Specified 2.1.0
Best Way to Create Custom Config Options For My Rails App
What Exactly Is the Singleton Class in Ruby
In Ruby on Rails, How to Format a Date With the "Th" Suffix, as In, "Sun Oct 5Th"
How to Find and Return a Duplicate Value in Array
Redirect_To Using Post in Rails
Is There Any Difference Between the ':Key =≫ "Value"' and 'Key: "Value"' Hash Notations