Understanding the "||" or Operator in If Conditionals in Ruby

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'

def b
'b method'

a && b
# 'a method'
# => false

b is never evaluated

def a
puts 'a method'

def b
'b method'

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


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 "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.


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) + "..."

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:

  1. assignment: @date = - set date to the value returned by the ternary statement
  2. condition: params[:month] - a month value - note: nil evaluates to false when used in a condition.
  3. true value: Date.parse(params[:month]) - Parse the month value as a date.
  4. 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
@date = Date.parse(params[:month])

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)
'Not 1'

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?

Related Topics

Leave a reply