« Back

🚨

some Ruby tips

on programming
last updated 6/12/21

Like most stuff on the internet, this is really just a list.

Recently I've spent the bulk of my time writing Ruby and thanks to my teammates, have gotten exposed to some nice techniques I had not seen before. Below are a few of the simplest ones.


percent strings

Especially with long arrays of strings, %w is handy because it saves us from copious punctuation. There's more on other types of percent strings here.


groceries = %w[eggs yogurt chicken]
# or... groceries = %w(eggs yogurt chicken)

groceries #=> ['eggs', 'yogurt', 'chicken']

# use %i for an array of symbols
groceries = %i[eggs yogurt chicken]

groceries #=> [:eggs, :yogurt, :chicken]
        

pretend flag

Running rails g --help or rails g -h outputs a detailed help message, including this flag:


-p, [--pretend], [--no-pretend] # Run but do not make any changes
        

We can append -p to any rails generate command to simulate what it does. 10/10 would recommend this before running rails destroy anything.


handling nil

I had typically used conditional statements to avoid calling methods on nil objects:

# blows up given a place that's nil
def get_city(place)
  place.address.city
end

get_city(a_real_place) #=> Realtown, USA
get_city(a_fake_place) #=> NoMethodError...

# this works
def get_city(place)
  place.address ? place.address.city : nil
end

get_city(a_real_place) #=> Realtown, USA
get_city(a_fake_place) #=> nil
        

But #try and the safe navigation operator &. are often simpler:


def get_city(place)
  place.address.try(:city)
end

get_city(a_real_place) #=> Realtown, USA
get_city(a_fake_place) #=> nil

def get_city(place)
  place.address&.city
end

get_city(a_real_place) #=> Realtown, USA
get_city(a_fake_place) #=> nil
        

#try can be difficult to debug because it will always return nil. A benefit of &., also known as the lonely operator, is that it will throw an error if the receiver doesn't respond to the method we're calling on it.

# if we spell 'city' incorrectly
def get_city(place)
  place.address.try(:citey)
end

get_city(a_fake_place) #=> nil

def get_city(place)
  place.address&.citey
end

get_city(a_fake_place) #=> NoMethodError...
        

#dig is also great because it works for hashes and arrays:


person = {
  name: 'Ethan',
  address_attributes: {
    city: 'Los Angeles',
    state: 'California'
  }
}

person.dig(:address_attributes, :city) #=> Los Angeles
person.dig(:address_attributes, :zip) #=> nil

states = [
  ['AL', 'AK', 'AZ'],
  ['AR', 'CA', 'CO']
]

state.dig(1, 1) #=> 'CA'
state.dig(1, 5) #=> nil