Ruby/Rails FYI
Interpolation
Interpolation automatically calls to_s
, so the to_s
calls in this sample text are unnecessary.
def s3_filename(record)
name = record.name || 'Empty '
date = Date.today.to_s
guid = UUIDTools::UUID.random_create.to_s
"#{name}-#{date}-#{guid}.txt"
end
Beginning or ending n characters of a word
If you see things like word[0..4]
or word[5..-1]
, you can instead use Rails ActiveSupport methods like first
, last
, to
, and from
.
Suppose word = 'foobar'
.
word.first(2) # fo
word.to(2) # foo
word.first(-2) # foob
word.to(-2) # fooba
word.last(2) # ar
word.from(2) # obar
word.last(-2) # obar
word.from(-2) # ar
Avoid []
Avoid calling my_hash[key]
. If the key isn’t defined, you’ll get nil
. This can lead to confusing errors:
user = my_hash[:user]
# Tens or hundreds of unrelated lines, then...
user.name # NoMethodError: undefined method `name' for nil:NilClass
Imagine you had this instead.
user = my_hash.fetch(:user) # KeyError: key not found: :user
That’s much clearer and makes for easier debugging.
- Even if the key might not be defined, you should still use
fetch
, because then it will communicate that possibility to future readers. Like this:my_hash.fetch(:key_that_might_not_be_present, nil)
- If you’re dealing with a
params
object, there’s a better more specific method thanfetch
, which isparams.require
.
If this seems a little verbose or your skeptical about the benefits, here are some other arguments to consider, from some of the most experienced Rubyists I’ve ever encountered.
Gary’s tweet seems to have disappeared. It was:
Ruby’s `[]` operator should almost never be used. You will die. Do `x.fetch(k)`. If you really want nil by default, do `x.fetch(k) { nil }`.
Superfluous begin/end
People often write unnecessary begin/end blocks, e.g.
def foobar
begin
# do a thing which may fail
rescue => e
# do some exception handling
end
end# That can be written simply as:
def foobar
# do a thing which may fail
rescue => e
# do some exception handling
end
Associations vs. ID’s
Bad: FactoryGirl.create(:user, company_id: company.id)
Good: FactoryGirl.create(:user, company: company)
Bad: validates(:company_id)
Good: validates(:company)