CrackedRuby logo

CrackedRuby

Pseudo Variables (self, nil, true, false)

Overview

Ruby includes four pseudo variables that form the foundation of object-oriented programming and boolean logic in the language:

  • self - References the current object context
  • nil - Represents the absence of a value
  • true - The boolean true value
  • false - The boolean false value

These pseudo variables are keywords in Ruby, meaning they're reserved and cannot be used as variable names. They provide consistent access to essential programming concepts across all Ruby code.

# self refers to the current object
class Person
  def initialize(name)
    @name = name
    puts self.class  # => Person
  end
end

# nil represents absence
user = nil
puts user.nil?  # => true

# Boolean values
active = true
disabled = false
puts active && !disabled  # => true

The self Pseudo Variable

The self pseudo variable always points to the current object - the receiver of the current method call. Understanding self is crucial for Ruby programming as it determines method dispatch and variable access.

Context Changes

The value of self changes based on where you are in your code:

puts self  # => main (top-level object)

class MyClass
  puts self  # => MyClass (the class object itself)

  def instance_method
    puts self  # => #<MyClass:0x...> (instance of MyClass)
  end

  def self.class_method
    puts self  # => MyClass (the class object)
  end
end

obj = MyClass.new
obj.instance_method  # self is the instance
MyClass.class_method  # self is the class

Method Dispatch

When you call a method without an explicit receiver, Ruby sends it to self:

class Calculator
  def add(a, b)
    log_operation("addition")  # Same as: self.log_operation("addition")
    a + b
  end

  private

  def log_operation(type)
    puts "Performing #{type}"
  end
end

Explicit Self Usage

Sometimes you need to explicitly use self to disambiguate or access certain features:

class Person
  attr_accessor :name

  def initialize(name)
    @name = name
  end

  def name=(new_name)
    # Must use self to call the setter method
    # Without self, this creates a local variable
    self.name = new_name.capitalize
  end

  def introduce
    # These are equivalent:
    puts name
    puts self.name
  end
end

The nil Pseudo Variable

nil is Ruby's representation of "nothing" or "no value." It's the only instance of the NilClass and is considered falsy in boolean contexts.

Falsy Behavior

In Ruby, only nil and false are falsy - everything else is truthy:

def check_value(value)
  if value
    puts "Truthy: #{value.inspect}"
  else
    puts "Falsy: #{value.inspect}"
  end
end

check_value(nil)     # => "Falsy: nil"
check_value(false)   # => "Falsy: false"
check_value(0)       # => "Truthy: 0"
check_value("")      # => "Truthy: \"\""
check_value([])      # => "Truthy: []"

Common Nil Patterns

# Safe navigation with nil
user = nil
puts user&.name  # => nil (doesn't raise an error)

# Nil coalescing
name = user&.name || "Anonymous"

# Checking for nil
if user.nil?
  puts "No user found"
end

# Compact removes nil values
array = [1, nil, 2, nil, 3]
puts array.compact  # => [1, 2, 3]

Nil in Collections

# Hash returns nil for missing keys
hash = { a: 1, b: 2 }
puts hash[:c]  # => nil

# Arrays return nil for out-of-bounds indices
array = [1, 2, 3]
puts array[10]  # => nil

# fetch provides alternatives to nil
puts hash.fetch(:c, "default")  # => "default"
puts hash.fetch(:c) { |key| "No #{key} found" }  # => "No c found"

The true and false Pseudo Variables

true and false are the only instances of TrueClass and FalseClass respectively. They represent boolean values and are fundamental to conditional logic.

Boolean Operations

# Logical AND
puts true && true    # => true
puts true && false   # => false
puts false && true   # => false

# Logical OR
puts true || false   # => true
puts false || false  # => false

# Logical NOT
puts !true   # => false
puts !false  # => true

# Short-circuit evaluation
puts false && some_expensive_method  # some_expensive_method never called
puts true || some_expensive_method   # some_expensive_method never called

Comparison Methods

# Object equality
puts true == true    # => true
puts false == false  # => true
puts true == false   # => false

# Type checking
puts true.class      # => TrueClass
puts false.class     # => FalseClass

# Conversion
puts !!1             # => true
puts !!nil           # => false
puts !!"hello"       # => true

Conditional Assignment

# Set default values
status ||= false
name ||= "Unknown"

# Conditional assignment with false
enabled = false
enabled ||= true  # => true (because false is falsy)

# Use fetch for explicit false handling
options = { debug: false }
debug = options.fetch(:debug, true)  # => false

Advanced Usage Patterns

Self in Different Contexts

module Greeter
  def self.included(base)
    puts "#{self} included in #{base}"
    base.extend(ClassMethods)
  end

  module ClassMethods
    def greet_all
      puts "Hello from #{self}"
    end
  end

  def greet
    puts "Hello from #{self.class}"
  end
end

class Person
  include Greeter
end

Person.greet_all  # => "Hello from Person"
Person.new.greet  # => "Hello from Person"

Method Missing with Self

class DynamicProxy
  def initialize(target)
    @target = target
  end

  def method_missing(method_name, *args, &block)
    if @target.respond_to?(method_name)
      puts "Proxying #{method_name} to #{@target} from #{self}"
      @target.send(method_name, *args, &block)
    else
      super
    end
  end

  def respond_to_missing?(method_name, include_private = false)
    @target.respond_to?(method_name, include_private) || super
  end
end

Nil Object Pattern

class NullUser
  def name
    "Guest"
  end

  def admin?
    false
  end

  def nil?
    false  # This is not actually nil
  end

  def present?
    false
  end
end

class UserService
  def find_user(id)
    # Instead of returning nil, return a null object
    User.find(id) || NullUser.new
  end
end

# Usage without nil checks
user = UserService.new.find_user(999)
puts user.name     # => "Guest" (no NoMethodError)
puts user.admin?   # => false

Common Pitfalls and Best Practices

Self Assignment Confusion

class Problem
  attr_accessor :value

  def bad_setter(new_value)
    # This creates a local variable, doesn't call the setter!
    value = new_value
    puts @value  # => nil
  end

  def good_setter(new_value)
    # This calls the setter method
    self.value = new_value
    puts @value  # => new_value
  end
end

Nil vs Empty Checks

# Be specific about what you're checking
def process_data(data)
  # Wrong: treats empty arrays/strings as invalid
  return "No data" if !data

  # Better: distinguish between nil and empty
  return "No data provided" if data.nil?
  return "Empty data" if data.respond_to?(:empty?) && data.empty?

  # Process data...
end

# Using present? and blank? (if using Rails)
def rails_way(data)
  return "Invalid" if data.blank?  # nil, false, empty, or whitespace
  # Process data...
end

Boolean Coercion Mistakes

# Common mistake: assuming truthiness equals true
def is_enabled?(value)
  # Wrong: returns any truthy value
  value

  # Better: explicitly return boolean
  !!value
end

# API design consideration
def status
  # Consider returning explicit booleans for clearer APIs
  @active ? true : false
end

Self in Blocks and Procs

class Counter
  def initialize
    @count = 0
  end

  def increment
    @count += 1
  end

  def process_items(items)
    # self changes inside different block types
    items.each do |item|
      puts self.class  # => Counter (self is preserved)
      increment        # Works - calls method on Counter instance
    end

    # With instance_eval, self changes
    items.each do |item|
      instance_eval do
        puts self.class  # => String (if item is a string)
        # increment would fail here
      end
    end
  end
end

Reference

Pseudo Variable Summary

Variable Type Description Assignable
self Various Current object context No
nil NilClass Absence of value No
true TrueClass Boolean true No
false FalseClass Boolean false No

Self Context Reference

Context Self Value
Top level main object
Class definition The class object
Module definition The module object
Instance method Instance of the class
Class method The class object
Block Outer scope's self
instance_eval block The receiver object

Truthiness Reference

Value Truthy Falsy
nil
false
true
0
""
[]
{}

Common Methods

Method Available On Returns Description
.nil? All objects Boolean True if receiver is nil
.class All objects Class Class of the object
! All objects Boolean Logical negation
!! All objects Boolean Double negation (converts to boolean)
.present? All objects (Rails) Boolean True if not blank
.blank? All objects (Rails) Boolean True if nil, false, empty, or whitespace