if var

    This also applies when a variable is assigned in an if‘s condition:

    1. if a = some_expression
    2. # here a is not nil
    3. end

    This logic also applies if there are ands (&&) in the condition:

    Of course, reassigning a variable inside the then branch makes that variable have a new type based on the expression assigned.

    The above logic works only for local variables. It doesn’t work with instance variables, class variables, or variables bound in a closure. The value of these kinds of variables could potentially be affected by another fiber after the condition was checked, rendering it nil. It also does not work with constants.

    1. if @a
    2. end
    3. if @@a
    4. # here `@@a` can be nil
    5. end
    6. closure = ->{ a = "foo" }
    7. if a
    8. # here `a` can be nil
    9. end

    Another option is to use Object#try found in the standard library which only executes the block if the value is not nil:

    1. @a.try do |a|
    2. end

    Method calls

    That logic also doesn’t work with proc and method calls, including getters and properties, because nilable (or, more generally, union-typed) procs and methods aren’t guaranteed to return the same more-specific type on two successive calls.