Overview
Ruby provides multiple comment mechanisms for documenting code, controlling interpreter behavior, and organizing source files. Comments serve three primary purposes: inline documentation for developers, structured documentation for tools like RDoc and YARD, and interpreter directives through magic comments.
The most common comment type uses the hash symbol (#
) to create single-line comments. Ruby ignores everything from the hash symbol to the end of the line during parsing. Multi-line comments use =begin
and =end
delimiters, though single-line comments are preferred in practice.
# Single-line comment
puts "Hello, World!" # End-of-line comment
=begin
Multi-line comment block
spanning several lines
=end
Magic comments provide special instructions to the Ruby interpreter, controlling encoding, string mutability, and other runtime behaviors. These comments must appear at the top of files or immediately after the shebang line to take effect.
# frozen_string_literal: true
# encoding: UTF-8
class User
# Regular documentation comment
attr_reader :name
end
Ruby's comment system integrates with documentation tools that parse specially formatted comments to generate API documentation. RDoc and YARD use different markup syntaxes within comments to create structured documentation with cross-references, parameter descriptions, and return value specifications.
Basic Usage
Single-line comments begin with #
and continue to the end of the line. Ruby supports comments at any position on a line, making them useful for both standalone documentation and inline explanations.
# Class definition for managing user accounts
class UserAccount
# Initialize new user with email and password
def initialize(email, password)
@email = email # Store email address
@password = hash_password(password) # Hash for security
end
private
# Hash password using bcrypt algorithm
def hash_password(password)
BCrypt::Password.create(password)
end
end
Multi-line comments use =begin
and =end
as delimiters. The delimiters must start at the beginning of their lines with no preceding whitespace. Ruby ignores all content between these markers during parsing.
=begin
This is a multi-line comment block.
It can span multiple lines and include
any content without affecting execution.
=end
puts "This code executes normally"
Comments can disable code temporarily without deleting it, useful during development and debugging. This technique preserves code for later use while preventing execution.
def process_data(data)
# Original implementation - keeping for reference
# data.map { |item| item.upcase }
# New optimized version
data.map(&:upcase)
end
End-of-line comments provide context for specific statements without requiring separate lines. This approach keeps related documentation close to the code it describes.
response = HTTP.get(url, timeout: 30) # 30 second timeout
parsed = JSON.parse(response.body) # Parse JSON response
user_id = parsed.dig('user', 'id') # Extract user ID safely
Advanced Usage
Magic comments control Ruby interpreter behavior and must appear within the first two lines of a file. The frozen_string_literal
magic comment makes all string literals in the file frozen by default, improving performance and preventing accidental mutations.
# frozen_string_literal: true
class StringProcessor
DEFAULT_MESSAGE = "Hello, World!" # Frozen string literal
def self.process(text)
# This would raise FrozenError due to magic comment
# text << " suffix"
# Instead, create new string
text + " suffix"
end
end
Encoding magic comments specify character encoding for source files containing non-ASCII characters. Ruby defaults to UTF-8, but explicit encoding declarations ensure consistent interpretation across different environments.
# encoding: ISO-8859-1
# frozen_string_literal: true
class LocalizedGreeting
SPANISH_GREETING = "¡Hola!" # ISO-8859-1 encoded
FRENCH_GREETING = "Bonjour!" # Works with specified encoding
end
RDoc formatting within comments creates structured documentation with markup for emphasis, lists, and cross-references. RDoc processes these specially formatted comments to generate HTML documentation.
class DatabaseConnection
# Creates new database connection with specified options.
#
# Options:
# * +host+ - Database server hostname
# * +port+ - Database server port (default: 5432)
# * +timeout+ - Connection timeout in seconds
#
# Returns DatabaseConnection instance or raises ConnectionError.
#
# Example:
# conn = DatabaseConnection.new(host: 'localhost', port: 5432)
# conn.connect!
def initialize(options = {})
@host = options[:host] || 'localhost'
@port = options[:port] || 5432
@timeout = options[:timeout] || 30
end
end
YARD documentation uses different markup syntax with typed parameters and return values. YARD provides more sophisticated type checking and generates richer documentation than RDoc.
class UserRepository
# Finds user by email address with optional includes
#
# @param email [String] the user's email address
# @param includes [Array<Symbol>] related models to include
# @return [User, nil] the user if found, nil otherwise
# @raise [ValidationError] if email format is invalid
# @example
# user = repo.find_by_email('user@example.com', [:posts, :comments])
def find_by_email(email, includes: [])
validate_email!(email)
User.includes(includes).find_by(email: email)
end
end
Conditional compilation using comments allows code to execute based on specific conditions or environments. This technique enables debugging code, feature flags, or environment-specific behavior.
class PaymentProcessor
def process_payment(amount, card)
# DEBUG: Log payment details in development
# puts "Processing payment: #{amount} with card #{card.last_four}" if ENV['DEBUG']
result = charge_card(amount, card)
# FEATURE_FLAG: New fraud detection
# result = apply_fraud_detection(result) if ENV['FRAUD_DETECTION_ENABLED']
result
end
end
Production Patterns
Consistent comment formatting establishes clear documentation standards across codebases. Teams adopt specific patterns for method documentation, class descriptions, and inline explanations to maintain readability and enable automated documentation generation.
# frozen_string_literal: true
# Service class for processing user registration workflow.
# Handles validation, email confirmation, and account setup.
#
# @example Basic usage
# service = UserRegistrationService.new
# result = service.register(email: 'user@example.com', password: 'secret')
# puts result.success? ? 'Registration successful' : result.error_message
class UserRegistrationService
# Registers new user with provided credentials
#
# @param email [String] user's email address
# @param password [String] user's chosen password
# @param options [Hash] additional registration options
# @option options [Boolean] :send_confirmation (true) send confirmation email
# @option options [String] :role ('user') initial user role
# @return [RegistrationResult] result object with success status and data
def register(email:, password:, **options)
# Validate input parameters
return failure('Invalid email') unless valid_email?(email)
return failure('Weak password') unless strong_password?(password)
# Check for existing user
return failure('Email already taken') if User.exists?(email: email)
# Create user account
user = User.create!(
email: email,
password: BCrypt::Password.create(password),
role: options[:role] || 'user'
)
# Send confirmation email if requested
ConfirmationMailer.deliver(user) if options.fetch(:send_confirmation, true)
success(user)
end
end
API documentation comments provide comprehensive information for public interfaces, including parameter types, return values, exceptions, and usage examples. This documentation enables other developers to use classes and methods effectively.
module Authentication
# JWT token management for user authentication
#
# Provides methods for generating, validating, and refreshing
# JSON Web Tokens used throughout the application.
class TokenManager
# Generates JWT token for authenticated user
#
# @param user [User] authenticated user instance
# @param expires_in [Integer] token expiration in seconds (default: 3600)
# @return [String] signed JWT token
# @raise [TokenGenerationError] if signing fails
# @example
# token = TokenManager.generate_token(current_user, expires_in: 7200)
# response.headers['Authorization'] = "Bearer #{token}"
def self.generate_token(user, expires_in: 3600)
payload = {
user_id: user.id,
email: user.email,
exp: Time.current.to_i + expires_in
}
JWT.encode(payload, Rails.application.secret_key_base, 'HS256')
rescue JWT::EncodeError => e
raise TokenGenerationError, "Failed to generate token: #{e.message}"
end
end
end
Code organization comments divide files into logical sections, making large classes and modules easier to navigate. These comments act as visual separators and provide context for groups of related methods.
class OrderProcessor
# =============================================================================
# PUBLIC API METHODS
# =============================================================================
def process_order(order_id)
# Implementation here
end
def cancel_order(order_id)
# Implementation here
end
# =============================================================================
# PAYMENT PROCESSING
# =============================================================================
private
def charge_payment(amount, payment_method)
# Payment processing logic
end
def refund_payment(transaction_id)
# Refund processing logic
end
# =============================================================================
# EMAIL NOTIFICATIONS
# =============================================================================
def send_confirmation_email(order)
# Email sending logic
end
def send_cancellation_email(order)
# Email sending logic
end
end
Common Pitfalls
Magic comment placement affects their functionality. Magic comments must appear within the first two lines of a file, and the frozen_string_literal
comment specifically must precede other magic comments except encoding declarations.
# WRONG: Magic comment appears too late
require 'json'
# frozen_string_literal: true
class BadExample
STRING = "mutable" # Still mutable due to incorrect placement
end
# CORRECT: Magic comment at file beginning
# frozen_string_literal: true
require 'json'
class GoodExample
STRING = "frozen" # Frozen due to correct placement
end
Encoding magic comments interact unexpectedly with certain character sequences. Files containing non-UTF-8 characters without proper encoding declarations can cause parsing errors or unexpected character interpretation.
# PROBLEMATIC: No encoding specified with special characters
class WeatherService
# This might cause issues depending on file encoding
DEGREE_SYMBOL = "°" # Could be interpreted incorrectly
end
# SAFER: Explicit encoding declaration
# encoding: UTF-8
class WeatherService
DEGREE_SYMBOL = "°" # Correctly interpreted as UTF-8
end
RDoc parsing fails when comment formatting doesn't follow expected patterns. Malformed markup, incorrect indentation, or missing required elements can cause documentation generation to skip methods or produce incomplete output.
class DocumentationExample
# PROBLEMATIC: Inconsistent indentation breaks RDoc parsing
#Creates new instance
# * param1 - first parameter
# * param2 - second parameter
# Returns: new instance
def bad_documentation(param1, param2)
end
# CORRECT: Consistent formatting for proper parsing
# Creates new instance
#
# Parameters:
# * +param1+ - first parameter description
# * +param2+ - second parameter description
#
# Returns new instance of class
def good_documentation(param1, param2)
end
end
Over-commenting creates maintenance overhead and reduces code readability. Comments that restate obvious code behavior or describe implementation details that frequently change become outdated quickly.
# PROBLEMATIC: Obvious and redundant comments
class UserCounter
# Initialize the counter
def initialize
@count = 0 # Set count to zero
end
# Increment the counter by one
def increment
@count += 1 # Add one to count
end
end
# BETTER: Comments provide value and context
class UserCounter
# Tracks active user sessions across multiple server instances
def initialize
@count = 0
end
# Thread-safe increment for concurrent access
def increment
@count += 1
end
end
Magic comment conflicts occur when multiple comments attempt to control the same interpreter behavior. The interpreter uses the first valid magic comment it encounters and ignores subsequent conflicting declarations.
# CONFLICTING: Second encoding comment is ignored
# encoding: UTF-8
# encoding: ASCII
class ConflictExample
# Ruby uses UTF-8 encoding despite second declaration
TEXT = "unicode: ∞"
end
Reference
Comment Types
Type | Syntax | Purpose | Example |
---|---|---|---|
Single-line | # comment text |
Inline documentation | # Calculate total price |
End-of-line | code # comment |
Statement annotation | total += tax # Add sales tax |
Multi-line | =begin...=end |
Block comments | =begin\nLong description\n=end |
Magic comment | # directive: value |
Interpreter control | # frozen_string_literal: true |
Magic Comments
Magic Comment | Values | Effect | Position |
---|---|---|---|
frozen_string_literal |
true , false |
Controls string mutability | First two lines |
encoding |
Encoding name | Sets file character encoding | First two lines |
warn_indent |
true , false |
Controls indentation warnings | First two lines |
shareable_constant_value |
literal , experimental_everything |
Ractor constant sharing | First two lines |
RDoc Markup
Markup | Syntax | Result |
---|---|---|
Bold | *text* |
text |
Emphasis | _text_ |
text |
Code | +code+ |
code |
Link | {Class} |
Class link |
List item | * or - |
Bullet point |
Numbered list | 1. |
Numbered item |
YARD Tags
Tag | Purpose | Syntax | Example |
---|---|---|---|
@param |
Parameter description | @param name [Type] description |
@param id [Integer] user ID |
@return |
Return value | @return [Type] description |
@return [User] found user |
@raise |
Exception | @raise [Exception] condition |
@raise [NotFoundError] if missing |
@example |
Usage example | @example\n code |
@example\n User.find(1) |
@deprecated |
Deprecation notice | @deprecated message |
@deprecated Use find_user instead |
@since |
Version added | @since version |
@since 2.1.0 |
@see |
Cross-reference | @see Class#method |
@see User#authenticate |
Comment Best Practices
Practice | Description | Example |
---|---|---|
Explain why, not what | Focus on reasoning and context | # Cache frequently accessed data to reduce DB queries |
Keep comments current | Update comments when code changes | Update parameter descriptions after method changes |
Use consistent formatting | Follow team documentation standards | Consistent indentation and markup |
Avoid obvious comments | Don't restate code behavior | Don't comment x = x + 1 # increment x |
Group related functionality | Use section headers for organization | # === Authentication Methods === |
Error Conditions
Error | Cause | Solution |
---|---|---|
SyntaxError |
Malformed multi-line comment | Ensure =begin and =end start at line beginning |
Encoding::InvalidByteSequenceError |
Character encoding mismatch | Add correct encoding magic comment |
Ignored magic comment | Wrong position in file | Move magic comment to first two lines |
RDoc parsing failure | Malformed markup syntax | Use consistent indentation and valid markup |