iwantcoding.com
🔥 Daily 👥 Rooms 🏆 Top Log in Sign up

Symbols

Symbols are immutable, interned identifiers — :status, :user_id. Cheaper than strings for hash keys / method names; the canonical “name of something.”

Symbols, comparison, conversions, hash keys

EXAMPLE
# 1) Literal
:status
:user_id
:'my-key with spaces'

# 2) Why symbols
# - Same content = same object (interned). Memory savings, fast comparison.
:foo.object_id == :foo.object_id       # true (always)
'foo'.object_id == 'foo'.object_id     # false (new string each time, in some modes)

# 3) Hash keys — use symbols for known fields
user = { id: 1, name: 'Ada', email: 'a@x.com' }
user[:name]                             # 'Ada'

# Old hash syntax (still valid)
user = { :id => 1, :name => 'Ada' }

# 4) Conversions
:hello.to_s          # 'hello'
'hello'.to_sym       # :hello
:hello.upcase        # :HELLO
:hello.length        # 5
:hello == :hello     # true
:hello.equal? :hello # true (same object)

# 5) Symbols as method names
class User
    attr_accessor :name, :email
end

User.instance_method(:name)
u = User.new
u.send(:name=, 'Ada')
u.send(:name)                          # 'Ada'
u.respond_to?(:name)                   # true

# 6) &:method shorthand — block from a symbol
names = ['ada', 'bo', 'cy']
names.map(&:upcase)                    # ['ADA', 'BO', 'CY']
names.map(&:length)                    # [3, 2, 2]
users.map(&:name)                      # like users.map { |u| u.name }

# 7) Compare strings vs symbols
'name' == :name                        # false — different types
:name.to_s == 'name'                   # true
# Use HashWithIndifferentAccess (Rails) when input may be either:
require 'active_support/core_ext/hash/indifferent_access'
h = { 'name' => 'Ada' }.with_indifferent_access
h[:name]                               # 'Ada' (works for both keys)

# 8) Common gotcha — symbols never get garbage collected before Ruby 2.2
# (Now: only frozen string literals and symbol-table entries from code, GC handles input symbols.)
# Still — don't generate symbols from untrusted input (DoS via memory growth).
user_input.to_sym                      # AVOID — attacker can fill symbol table

# 9) Keyword arguments use symbols
def create_user(name:, email:, role: :user)
    # ...
end

create_user(name: 'Ada', email: 'a@x.com')
create_user(name: 'Cy',  role: :admin)

# 10) Pattern matching with symbols (Ruby 3+)
case msg
in { type: :login, user: }
    handle_login(user)
in { type: :logout }
    handle_logout
in { type: :error, reason: String => r }
    log_error(r)
end

# 11) Enumerable methods that take a symbol
numbers.reduce(:+)                     # sum
numbers.inject(:*)                     # product
strings.sort_by(&:length)              # by length
rows.group_by(&:status)                # group by status method

# 12) Hash with symbol keys — rich API
h = { name: 'Ada', age: 32, role: :admin }
h.each_pair { |k, v| puts "\#{k}=\#{v}" }
h.transform_keys(&:to_s)               # string keys
h.slice(:name, :age)                   # subset
h.fetch(:role) { :user }               # default block
h.dig(:profile, :city)                 # nested access

# 13) Use symbols for...
#   - Hash keys when the set is known and finite (user[:name], user[:email])
#   - Method names passed around (object.send(:method))
#   - Status / enum values (:active, :paused, :banned)
#   - Constants you'd write as :ROLE_ADMIN in C

# 14) Don't use symbols for...
#   - User input that you'd parse to a symbol — DoS risk
#   - Anything that needs mutation (symbols are immutable)
#   - Display strings (they print weird with their colon)

# 15) Symbol procs in real code
users.select(&:active?).map(&:email)
emails = users.map(&:email).reject(&:nil?).uniq

# 16) Rails convention
#   has_many :posts, dependent: :destroy
#   validates :email, presence: true, format: { with: URI::MailTo::EMAIL_REGEXP }
#   render :index
#   scope :recent, -> { order(created_at: :desc) }

# 17) Modern Ruby — symbol shorthand for hash literals (3.1+)
# Same name on both sides:
name = 'Ada'
email = 'a@x.com'
u = { name:, email: }                  # → { name: 'Ada', email: 'a@x.com' }

Why it matters

Symbols are Ruby’s “name of something.” Use for hash keys, method names, finite enums; avoid for user input (DoS risk) and display strings. &:method shorthand cleans up half your blocks.

Tip: Tweak the snippet with Try it Yourself », then sit the quiz at the bottom of the page.

Example

Example
status = :active
puts status.to_s
puts status == :active
Try it Yourself »

Discussion

Loading…