🚨
some Ruby tips
on programminglast 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