Ruby on Rails — “Poetry Mode”

Haleigh Dalke
4 min readJul 14, 2020

--

One of the great advantages of programming in Ruby is its resemblance to the English language. Ruby was designed to be intuitively read, and so it is common practice for advanced Ruby programmers to follow conventions of poetry mode.

Poetry mode is characterized by simplicity. It should be as thoughtfully written and as easy to read as poetry. Unlike many other programming languages such as Python and Java, Ruby does not contain primitive data types. All data is treated as objects, which provides us a huge advantage when simplifying our code! Poetry mode allows us to omit parenthesis around method arguments and curly braces around a hash, so long as the code is syntactically unambiguous. Although Ruby regards these conventions as good programming practice, its flexibility and historical lack of common standards have allowed for numerous ways and styles to do just about everything.

Ruby was designed to make programmers happy. Semicolons, for example, are completely omitted:

# Option 1
puts 'ruby is awesome';
# Option 2
puts 'ruby is awesome'

Though technically correct, never use semicolons to terminate statements and expressions. Unlike many other languages, Ruby does not require you to use semicolons.

A method return keyword can be written implicitly by writing the return value one line above the end of the method. For example:

# explicit return
def some_method
sum = 3 + 4
return sum
end
# implicit return
def some_method
3 + 4
end

Much faster to type and easier to read, right? Another important rule of poetry mode is to omit curly brackets and parenthesis in syntactically unambiguous situations. The following are two examples of appropriate times to omit the brackets:

# Omit outer braces around implicit options hash# bad
user.set({ name: 'John', age: 45, permissions: { read: true } })
# good
user.set(name: 'John', age: 45, permissions: { read: true })
# -------# Omit both outer braces and parenthesis for methods that are apart of an internal DSLclass Person < ActiveRecord::Base
# bad
validates(:name, { presence: true, length: { within: 1..10 } })

# good
validates :name, presence: true, length: { within: 1..10 }
end

When it comes to conditionals, Ruby prefers that you omit parenthesis around the conditional statement (`if` statements and loops) and provides you with the option of using a ternary operator. If you have only one expression per branch of an if statement, you may want to use a ternary operator:

# Omit parenthesis:# bad 
if (x > 10)
# body omitted
end
# good
if x > 10
# body omitted
end
# -------# Use ternary operator in these situations:# bad
result = if some_condition then something else something_else end
if some_condition
do_something
end
# good
result = some_condition ? something : something_else
do_something if some_condition some_condition && do_something

You may also omit parenthesis around arguments in a method declaration, but be sure to do so unambiguously.

Ruby provides many shorthands for self-assignment, conditional variable initialization, and existence check (see documentation). For self-assignment, use the following shorthands when possible:

# bad 
x = x + y
x = x * y
x = x**y
x = x / y
x = x || y
x = x && y
# good
x += y
x *= y
x **= y
x /= y
x ||= y
x &&= y

Blocks of code follow a similar convention as the ternary operator. When you have a single line within the block, use {} for efficiency, otherwise use do/end for readability. For example:

# bad 
names.each do |name|
puts name
end
# good
names.each { |name| puts name }

Ah, much easier. It’s important to note that method definitions do not follow this convention. Always separate lines in method definitions, even if you only have a single line in the body:

# bad
def
some_method() body end
# good
def some_method
body
end

When defining collections, use the following conventions:

# Use %w for an array of words (non-empty strings without spaces and special characters)# bad 
STATES = ['draft', 'open', 'closed']

# good
STATES = %w[draft open closed]
# ----------# Use %i for an array of symbols# bad
STATES = [:draft, :open, :closed]
# good
STATES = %i[draft open closed]

Lastly, Ruby strings are similar to other languages — interpolate strings where possible and adopt a consistent string styling format in your program:

# bad 
email_with_name = user.name + ' <' + user.email + '>'
# good
email_with_name = "#{user.name} <#{user.email}>"
# good
email_with_name = format('%s <%s>', user.name, user.email)

That’s poetry mode for you! As you can see, Ruby places a lot of importance on simplicity, fewer keystrokes, and readability. Ruby wants to make your life as a programmer easier — be sure to study these conventions now to save yourself a headache later. Happy coding!

Resources: “The Ruby Style Guide,” Course Hero, “Poetry of Programming,” and “The ‘Poetry’ of Ruby.”

--

--