Ruby Style Guidelines
Comprehensive style guide for writing clean, maintainable Ruby code at Kalkomey.
Source Code Layout
Indentation and Spacing
- Use 2 spaces for indentation. No tabs.
- Keep lines under 120 characters.
- No trailing whitespace.
- End each file with a newline.
# Good
class Person
def initialize(name)
@name = name
end
end
# Bad - wrong indentation
class Person
def initialize(name)
@name = name
end
end
Line Breaks
- Add empty lines between method definitions.
- Add empty lines between logical paragraphs.
- Don't add empty lines after method opening or before method ending.
# Good
class Person
def full_name
[first_name, last_name].compact.join(' ')
end
def age
Time.current.year - birth_year
end
private
attr_reader :birth_year
end
# Bad - no separation between methods
class Person
def full_name
[first_name, last_name].compact.join(' ')
end
def age
Time.current.year - birth_year
end
private
attr_reader :birth_year
end
Alignment
- Align multiline parameters with the first parameter.
- Align multiline array elements and hash key-value pairs.
# Good
def send_mail(to:,
subject:,
body:)
# Method body
end
# Good
hash = {
foo: 'bar',
bazz: 'qux',
quux: 'corge'
}
# Bad
hash = {
foo: 'bar',
bazz: 'qux',
quux: 'corge'
}
Naming Conventions
General Guidelines
- Use snake_case for methods and variables.
- Use CamelCase for classes and modules.
- Use SCREAMING_SNAKE_CASE for constants.
# Good
class UserAuthentication
MAXIMUM_ATTEMPTS = 3
def authenticate_user
check_credentials
end
private
def check_credentials
# Implementation
end
end
# Bad
class userAuthentication
MaximumAttempts = 3
def AuthenticateUser
CheckCredentials
end
end
Method Names
- Use question mark suffix for boolean methods.
- Use exclamation mark suffix for destructive methods.
- Use verb phrases for method names that perform actions.
# Good
class User
def active?
status == 'active'
end
def activate!
self.status = 'active'
save!
end
def calculate_age
Time.current.year - birth_year
end
end
# Bad
class User
def is_active
status == 'active'
end
def activate
self.status = 'active'
save!
end
def age
Time.current.year - birth_year
end
end
Variable Names
- Choose descriptive and unambiguous names for variables.
-
Use short names for temporary variables, such as
ifor loop counters. -
Use prefixes like
min_ormax_to clarify range variables.
# Good
min_age = 18
max_age = 65
loop_index = 0
# Bad
x = 18
y = 65
i = 0
Syntax
Parentheses
- Use parentheses around method arguments when not clear without them.
- Omit parentheses for DSLs and methods that are clear without them.
# Good
puts('Hello, World!')
# Bad
puts 'Hello, World!'
# Good in DSLs
validates :email, presence: true
Literals
- Use symbols instead of strings for keys in hashes.
-
Use
%wor%ifor arrays of words or symbols.
# Good
hash = { name: 'John', age: 30 }
array = %w[apple banana cherry]
# Bad
hash = { 'name' => 'John', 'age' => 30 }
array = ['apple', 'banana', 'cherry']
Classes & Modules
Class Definitions
-
Use
classkeyword for class definitions. -
Use
modulekeyword for modules.
# Good - class definition with inheritance and module inclusion.
class Person < ApplicationRecord
include Addressable
# Implementation
end
Class Inheritance
-
Use
<for class inheritance andincludefor module inclusion. -
Use
prependfor module inclusion when overriding methods.
Control Structures
Conditionals
- Use `if` for general conditions; use `unless` only for negative conditions.
- Prefer single-line conditionals for simple statements.
# Good
return if completed?
# Bad
if !completed?
return
end
Case Statements
- Use `case` for multiple conditions.
- Avoid deeply nested case statements.
# Good
case role
when 'admin'
access_admin_panel
when 'user'
access_dashboard
else
deny_access
end
Collections
Enumerables
- Use `each`, `map`, and `select` instead of `for` loops.
- Prefer `reduce` for aggregations.
# Good
names = users.map(&:name)
admins = users.select(&:admin?)
# Bad
names = []
for user in users
names << user.name
end
Regular Expressions
Best Practices
- Use `/x` flag for readability in complex patterns.
- Escape special characters to avoid unintended behavior.
# Good
regex = /
^\d{3}- # Area code
\d{3}- # Prefix
\d{4}$ # Line number
/x
# Bad
regex = /^\d{3}-\d{3}-\d{4}$/
Metaprogramming
When to Use
- Use sparingly for reducing boilerplate code.
- Document metaprogramming constructs clearly.
# Good
class Person
ATTRIBUTES = %i[first_name last_name]
ATTRIBUTES.each do |attr|
define_method(attr) do
instance_variable_get("@#{attr}")
end
end
end