Convention Over Configuration in Rails – Complete Guide with Examples

Convention Over Configuration in Rails – Complete Guide with Examples

Convention Over Configuration in Ruby on Rails

1. Introduction to Convention Over Configuration

1.1 What is “Convention Over Configuration”?

“Convention Over Configuration” (CoC) is a software design principle that prioritizes sensible defaults and standard naming conventions over explicit configuration. In simple terms, it means:

Core Principle: “If you follow the standard naming and folder structures, you don’t have to write extra configuration code.”

🎯 The Philosophy Behind CoC

Convention Over Configuration is based on the belief that:

  • ✅ Most applications follow similar patterns – Why reinvent the wheel?
  • ✅ Standardization improves productivity – Less time configuring, more time building
  • ✅ Consistency aids learning – Once you learn the patterns, you can work anywhere
  • ✅ Reduced cognitive load – Focus on business logic, not boilerplate

🔍 Real-World Analogy

Think of Convention Over Configuration like driving a car:

  • 🚗 Convention: Gas pedal = accelerate, brake pedal = stop, steering wheel = turn
  • ⚙️ Configuration: You’d have to manually configure which pedal does what every time
  • 💡 Result: You can drive any car without reading a manual
Example in Rails:
rails generate model User name:string email:string
Automatically creates:
  • • Model: app/models/user.rb
  • • Migration: db/migrate/xxx_create_users.rb
  • • Test file: test/models/user_test.rb
  • • Factory: test/factories/users.rb

1.2 Why is CoC Important in Rails?

🚀 Speed of Development

Convention Over Configuration dramatically speeds up development by eliminating the need to make countless decisions about structure and setup:

Without Conventions (Configuration Over Convention):
// You’d need to configure everything manually
// – Database table names
// – Model associations
// – Controller actions
// – View file locations
// – Route definitions
// – Form field names
// – And hundreds more…
With Conventions (Convention Over Configuration):
# Rails automatically knows:
# – User model → users table
# – has_many :posts → posts table with user_id
# – UsersController → User model
# – show action → views/users/show.html.erb
# – resources :users → 7 RESTful routes
# – form_for @user → correct field names

🔧 Maintainability

Consistent conventions make applications easier to maintain and scale:

  • 🔧 Predictable Changes: Know exactly where to make modifications
  • 🔧 Automated Tools: Generators, analyzers, and linters work seamlessly
  • 🔧 Debugging: Issues are easier to trace and fix
  • 🔧 Refactoring: Changes can be made systematically

1.3 Benefits of Following Conventions

⚡ Immediate Benefits

🎯 1. Faster Development

Before: Spend hours configuring database connections, setting up routes, creating boilerplate code

After: Focus on business logic while Rails handles the infrastructure

🎯 2. Reduced Errors

Before: Typos in configuration files, mismatched naming, broken associations

After: Rails validates conventions and provides helpful error messages

🎯 3. Better Code Quality

Before: Inconsistent patterns, hard-to-maintain code

After: Consistent, readable, maintainable code following proven patterns

🚀 Long-term Benefits

  • 📈 Scalability: Applications grow without becoming unmanageable
  • 📈 Team Growth: Easy to add new developers to the project
  • 📈 Technology Updates: Rails upgrades are smoother with conventional code
  • 📈 Community Support: Easier to get help when following conventions

💼 Business Benefits

  • 💰 Cost Reduction: Less time spent on configuration and debugging
  • 💰 Faster Time to Market: Features ship quicker
  • 💰 Lower Maintenance Costs: Easier to maintain and update
  • 💰 Reduced Risk: Fewer bugs and deployment issues

2. Rails Conventions Deep Dive

2.1 Naming Conventions

Rails uses specific naming conventions to automatically connect different parts of your application. These conventions are the foundation of Convention Over Configuration.

📝 Model Naming

  • ✅ Singular, PascalCase: User, BlogPost, OrderItem
  • ✅ File name: user.rb, blog_post.rb
  • ✅ Table name: users, blog_posts

🎮 Controller Naming

  • ✅ Plural, PascalCase + Controller: UsersController, BlogPostsController
  • ✅ File name: users_controller.rb, blog_posts_controller.rb

📁 View Naming

  • ✅ Folder: app/views/users/
  • ✅ Files: index.html.erb, show.html.erb
Example: User Management System
# Model: app/models/user.rb
class User < ApplicationRecord
has_many :posts
end

# Controller: app/controllers/users_controller.rb
class UsersController < ApplicationController
def index
@users = User.all
end
end

# View: app/views/users/index.html.erb
<h1>All Users</h1>
<% @users.each do |user| %>
<p><%= user.name %></p>
<% end %>

2.2 Folder Structure Conventions

Rails applications follow a standardized folder structure that organizes code by functionality and makes it easy to locate files.

📂 Standard Rails Directory Structure

app/
├── controllers/ # Controller classes
├── models/ # Model classes
├── views/ # View templates
├── helpers/ # View helper modules
├── mailers/ # Mailer classes
├── jobs/ # Background job classes
├── channels/ # Action Cable channels
├── assets/ # Images, stylesheets, JavaScript
└── javascript/ # JavaScript files

config/
├── routes.rb # URL routing
├── database.yml # Database configuration
└── application.rb # Application configuration

db/
├── migrate/ # Database migration files
└── seeds.rb # Database seed data

lib/
└── tasks/ # Custom Rake tasks

test/
├── models/ # Model tests
├── controllers/ # Controller tests
└── integration/ # Integration tests
Example: Blog Application Structure
When you create a blog post feature, Rails automatically creates:
• app/models/post.rb – Post model
• app/controllers/posts_controller.rb – Posts controller
• app/views/posts/ – Views folder
• db/migrate/xxx_create_posts.rb – Database migration
• test/models/post_test.rb – Model test
• test/controllers/posts_controller_test.rb – Controller test

2.3 Database Conventions

Rails database conventions ensure consistency between your models and database structure, automatically handling relationships and common fields.

🗄️ Table Naming

  • ✅ Plural, snake_case: users, blog_posts, order_items
  • ✅ Join tables: users_roles (alphabetical order)

🔗 Foreign Key Naming

  • ✅ Singular model name + _id: user_id, post_id
  • ✅ Polymorphic: commentable_id, commentable_type

⏰ Automatic Timestamps

  • ✅ created_at: Automatically set when record is created
  • ✅ updated_at: Automatically updated when record is modified
Example: E-commerce Database Structure
# Migration: db/migrate/xxx_create_orders.rb
class CreateOrders < ActiveRecord::Migration[7.0]
def change
create_table :orders do |t|
t.references :user, null: false, foreign_key: true
t.decimal :total_amount, precision: 10, scale: 2
t.string :status, default: ‘pending’
t.timestamps
end

end
end

# Model: app/models/order.rb
class Order < ApplicationRecord
belongs_to :user
has_many :order_items
end

# Rails automatically:
# – Uses ‘orders’ table
# – Creates user_id foreign key
# – Adds created_at and updated_at
# – Handles timestamps automatically

2.4 Controller Conventions

Rails controllers follow RESTful conventions with standard actions and naming patterns that automatically map to routes and views.

🎮 Standard RESTful Actions

  • ✅ index: Display all records
  • ✅ show: Display single record
  • ✅ new: Display form for new record
  • ✅ create: Save new record
  • ✅ edit: Display form for editing
  • ✅ update: Save changes to record
  • ✅ destroy: Delete record

📝 Controller Naming

  • ✅ Plural model name + Controller: UsersController
  • ✅ File location: app/controllers/users_controller.rb
  • ✅ Inheritance: Must inherit from ApplicationController
Example: Products Controller
# app/controllers/products_controller.rb
class ProductsController < ApplicationController
before_action :set_product, only: [:show, :edit, :update, :destroy]

def index
@products = Product.all
end

def show
# @product is set by before_action
end

def new
@product = Product.new
end

def create
@product = Product.new(product_params)
if @product.save
redirect_to @product, notice: ‘Product created successfully.’
else
render :new
end
end

private
def set_product
@product = Product.find(params[:id])
end

def product_params
params.require(:product).permit(:name, :price, :description)
end
end

2.5 Model Conventions

Rails models represent database tables and handle business logic, following conventions for associations, validations, and naming.

📊 Model Naming

  • ✅ Singular, PascalCase: User, BlogPost
  • ✅ File location: app/models/user.rb
  • ✅ Inheritance: Must inherit from ApplicationRecord

🔗 Association Conventions

  • ✅ belongs_to: Foreign key in this table
  • ✅ has_many: Foreign key in other table
  • ✅ has_one: One-to-one relationship
  • ✅ has_many :through: Many-to-many through join table

✅ Validation Conventions

  • ✅ presence: Field must not be blank
  • ✅ uniqueness: Field must be unique
  • ✅ length: Field length constraints
  • ✅ format: Field format validation
Example: Blog Post Model
# app/models/post.rb
class Post < ApplicationRecord
belongs_to :user
has_many :comments, dependent: :destroy
has_many :tags, through: :post_tags

validates :title, presence: true, length: { minimum: 5 }
validates :content, presence: true, length: { minimum: 50 }
validates :slug, presence: true, uniqueness: true

before_create :generate_slug

scope :published, -> { where(published: true) }
scope :recent, -> { order(created_at: :desc) }

private

def generate_slug
self.slug = title.parameterize
end
end

# Rails automatically:
# – Uses ‘posts’ table
# – Creates user_id foreign key
# – Handles timestamps
# – Provides finder methods

2.6 View Conventions

Rails views follow a hierarchical structure that automatically maps to controller actions and provides a consistent way to organize templates.

📁 View File Structure

  • ✅ Controller folder: app/views/users/
  • ✅ Action files: index.html.erb, show.html.erb
  • ✅ Layout files: application.html.erb
  • ✅ Partial files: _form.html.erb, _user.html.erb

🎨 Template Conventions

  • ✅ ERB templates: .html.erb for HTML
  • ✅ JSON templates: .json.jbuilder for APIs
  • ✅ Partial naming: Start with underscore _partial.html.erb
  • ✅ Instance variables: @user, @users
Example: User Views Structure
# app/views/users/index.html.erb
<h1>All Users</h1>
<%= link_to ‘New User’, new_user_path, class: ‘btn btn-primary’ %>

<div class=”users-grid”>
<% @users.each do |user| %>
<%= render ‘user’, user: user %>
<% end %>
</div>

# app/views/users/_user.html.erb (partial)
<div class=”user-card”>
<h3><%= user.name %></h3>
<p><%= user.email %></p>
<%= link_to ‘View Profile’, user_path(user) %>
</div>

# app/views/users/show.html.erb
<h1><%= @user.name %></h1>
<p>Email: <%= @user.email %></p>
<p>Member since: <%= @user.created_at.strftime(‘%B %Y’) %></p>

<%= link_to ‘Edit’, edit_user_path(@user) %> |
<%= link_to ‘Back to Users’, users_path %>

2.7 Route Conventions

Rails routing conventions automatically create RESTful routes based on resource names, providing a consistent API structure.

🛣️ RESTful Route Conventions

  • ✅ resources :users creates 7 standard routes
  • ✅ GET /users → users#index
  • ✅ GET /users/new → users#new
  • ✅ POST /users → users#create
  • ✅ GET /users/:id → users#show
  • ✅ GET /users/:id/edit → users#edit
  • ✅ PATCH/PUT /users/:id → users#update
  • ✅ DELETE /users/:id → users#destroy

🔗 Nested Routes

  • ✅ resources :users do
  • ✅ resources :posts
  • ✅ end
  • ✅ Creates: /users/:user_id/posts
Example: Blog Routes Configuration
# config/routes.rb
Rails.application.routes.draw do
root ‘home#index’

resources :users do
resources :posts, only: [:index, :new, :create]
end

resources :posts, except: [:new, :create] do
resources :comments, only: [:create, :destroy]
end

get ‘/about’, to: ‘pages#about’
get ‘/contact’, to: ‘pages#contact’

# Generated routes:
# GET /users/:user_id/posts
# GET /users/:user_id/posts/new
# POST /users/:user_id/posts
# GET /posts/:id
# GET /posts/:id/edit
# PATCH /posts/:id
# DELETE /posts/:id
# POST /posts/:post_id/comments
# DELETE /posts/:post_id/comments/:id
end

2.8 Migration Conventions

Rails migrations follow naming conventions that describe the database changes and automatically generate the correct table structure.

📝 Migration Naming

  • ✅ Create table: CreateUsers
  • ✅ Add column: AddEmailToUsers
  • ✅ Remove column: RemoveEmailFromUsers
  • ✅ Add index: AddIndexToUsersEmail

🗄️ Column Type Conventions

  • ✅ string: Short text (255 characters)
  • ✅ text: Long text (unlimited)
  • ✅ integer: Whole numbers
  • ✅ decimal: Decimal numbers with precision
  • ✅ boolean: True/false values
  • ✅ datetime: Date and time
Example: E-commerce Product Migration
# db/migrate/20231201_create_products.rb
class CreateProducts < ActiveRecord::Migration[7.0]
def change
create_table :products do |t|
t.string :name, null: false
t.text :description
t.decimal :price, precision: 10, scale: 2, null: false
t.string :sku, null: false
t.integer :stock_quantity, default: 0
t.boolean :active, default: true
t.references :category, null: false, foreign_key: true
t.timestamps
end

add_index :products, :sku, unique: true
add_index :products, :name
end
end

# Rails automatically:
# – Creates ‘products’ table
# – Adds category_id foreign key
# – Creates created_at and updated_at
# – Adds indexes for performance

2.9 Mailer Conventions

Rails mailers follow conventions for organizing email templates and methods, making it easy to send structured emails.

📧 Mailer Naming

  • ✅ Mailer class: UserMailer, OrderMailer
  • ✅ File location: app/mailers/user_mailer.rb
  • ✅ Inheritance: Must inherit from ApplicationMailer

📁 Mailer View Structure

  • ✅ View folder: app/views/user_mailer/
  • ✅ HTML template: welcome_email.html.erb
  • ✅ Text template: welcome_email.text.erb
Example: User Welcome Mailer
# app/mailers/user_mailer.rb
class UserMailer < ApplicationMailer
def welcome_email(user)
@user = user
@url = user_url(@user)

mail(to: @user.email, subject: ‘Welcome to Our Site!’)
end

def password_reset(user)
@user = user
@reset_url = edit_password_reset_url(@user.reset_token)

mail(to: @user.email, subject: ‘Password Reset Request’)
end
end

# app/views/user_mailer/welcome_email.html.erb
<!DOCTYPE html>
<html>
<head>
<meta content=’text/html; charset=UTF-8′ http-equiv=’Content-Type’ />
</head>
<body>
<h1>Welcome to our site, <%= @user.name %>!</h1>
<p>You have successfully signed up to our site.</p>
<p>To login to the site, just follow this link: <%= @url %>.</p>
<p>Thanks for joining and have a great day!</p>
</body>
</html>

2.10 Background Job Conventions

Rails background jobs follow conventions for organizing asynchronous tasks and ensuring they run efficiently in the background.

⚡ Job Naming

  • ✅ Job class: SendWelcomeEmailJob, ProcessOrderJob
  • ✅ File location: app/jobs/send_welcome_email_job.rb
  • ✅ Inheritance: Must inherit from ApplicationJob

🔄 Job Method Conventions

  • ✅ perform: Main method that executes the job
  • ✅ perform_later: Enqueue job for background execution
  • ✅ perform_now: Execute job immediately
Example: Email Processing Job
# app/jobs/send_welcome_email_job.rb
class SendWelcomeEmailJob < ApplicationJob
queue_as :default

def perform(user_id)
user = User.find(user_id)
UserMailer.welcome_email(user).deliver_now
rescue ActiveRecord::RecordNotFound
Rails.logger.error “User #{user_id} not found for welcome email”
end
end

# app/jobs/process_order_job.rb
class ProcessOrderJob < ApplicationJob
queue_as :orders

def perform(order_id)
order = Order.find(order_id)

# Process payment
PaymentProcessor.process(order)

# Update inventory
order.order_items.each do |item|
item.product.decrement!(:stock_quantity, item.quantity)
end

# Send confirmation email
OrderMailer.confirmation(order).deliver_now

order.update!(status: ‘processed’)
end
end

# Usage in controller:
# SendWelcomeEmailJob.perform_later(user.id)
# ProcessOrderJob.perform_later(order.id)

3. Best Practices

3.1 When to Follow Conventions

Following Rails conventions is generally the best approach for most scenarios. Here’s when you should stick to the conventions.

✅ Standard CRUD Operations

Always follow conventions for standard Create, Read, Update, Delete operations:

  • 🎯 User management: Users, profiles, authentication
  • 🎯 Content management: Posts, articles, pages
  • 🎯 E-commerce: Products, orders, categories
  • 🎯 Social features: Comments, likes, follows

✅ Team Development

Conventions are essential when working in teams:

  • 👥 New team members: Can understand code immediately
  • 👥 Code reviews: Everyone knows what to expect
  • 👥 Maintenance: Any developer can work on any part
  • 👥 Documentation: Code is self-documenting

✅ Learning and Growth

Conventions help with learning and career development:

  • 📚 Skill transfer: Knowledge applies to any Rails project
  • 📚 Community support: Easier to get help online
  • 📚 Best practices: Conventions embody years of experience
  • 📚 Career growth: Understanding conventions makes you valuable
Example: Following Conventions for User Management
# ✅ Good: Following conventions
class UsersController < ApplicationController
def index
@users = User.all
end

def show
@user = User.find(params[:id])
end

def create
@user = User.new(user_params)
if @user.save
redirect_to @user
else
render :new
end
end
end
🎯 When to Follow Conventions:
• Building standard web applications
• Working in teams or open source
• Learning Rails or teaching others
• Maintaining existing Rails applications
• Building features that Rails handles well

3.2 When to Break Conventions

While conventions are powerful, there are legitimate reasons to break them. Here’s when it’s appropriate to deviate.

🚀 Performance Requirements

Break conventions when performance is critical:

  • ⚡ Custom database queries: When ActiveRecord is too slow
  • ⚡ Non-standard caching: When Rails caching isn’t sufficient
  • ⚡ Custom routing: When RESTful routes don’t fit
  • ⚡ Background processing: When you need custom job queues

🔒 Security Requirements

Security sometimes requires breaking conventions:

  • 🔐 Custom authentication: When Devise doesn’t meet requirements
  • 🔐 Custom authorization: When CanCanCan/Pundit aren’t sufficient
  • 🔐 Custom validation: When Rails validations aren’t enough
  • 🔐 Custom encryption: When you need specific encryption methods

🎯 Business Logic Complexity

Complex business logic may require custom approaches:

  • 💼 Service objects: For complex business operations
  • 💼 Custom models: When ActiveRecord doesn’t fit the domain
  • 💼 Custom controllers: When REST doesn’t match the workflow
  • 💼 Custom views: When standard templates don’t work
Example: Breaking Conventions for Performance
# ⚡ Performance: Custom SQL for complex reporting
class ReportController < ApplicationController
def sales_summary
@sales_data = ActiveRecord::Base.connection.execute(
“SELECT DATE(created_at) as date,
SUM(total) as daily_total,
COUNT(*) as order_count
FROM orders
WHERE created_at >= ?
GROUP BY DATE(created_at)
ORDER BY date DESC”,
[30.days.ago]
)
end
end
Example: Custom Service Object for Complex Logic
# 💼 Business Logic: Custom service for order processing
class OrderProcessingService
def initialize(order)
@order = order
end

def process
return false unless validate_order
return false unless process_payment
return false unless update_inventory
return false unless send_notifications

@order.update!(status: ‘processed’)
true
end

private

def validate_order
# Complex validation logic
end

def process_payment
# Payment processing logic
end

def update_inventory
# Inventory update logic
end

def send_notifications
# Notification logic
end
end
⚠️ When Breaking Conventions:
• Document your decisions clearly
• Ensure the team understands why
• Consider the maintenance cost
• Test thoroughly
• Have a plan to refactor later if possible

3.3 Team Guidelines and Standards

Establishing clear guidelines helps teams work efficiently with Rails conventions while maintaining code quality.

📋 Code Style Guidelines

  • 📝 Follow Ruby style guide: Use RuboCop for consistency
  • 📝 Naming conventions: Always use Rails naming patterns
  • 📝 File organization: Keep files in standard Rails locations
  • 📝 Comment standards: Document complex logic, not obvious code

👥 Team Communication

  • 💬 Code reviews: Always review for convention compliance
  • 💬 Pull requests: Include explanation for any convention breaks
  • 💬 Documentation: Document custom patterns and decisions
  • 💬 Knowledge sharing: Regular sessions on Rails conventions

🔄 Development Workflow

  • 🛠️ Git workflow: Use conventional commit messages
  • 🛠️ Testing: Write tests that follow Rails testing conventions
  • 🛠️ Deployment: Use Rails deployment best practices
  • 🛠️ Monitoring: Follow Rails monitoring conventions
Example: Team Style Guide
# .rubocop.yml – Team style configuration
AllCops:
TargetRubyVersion: 3.0
NewCops: enable

Style/Documentation:
Enabled: false

Style/StringLiterals:
EnforcedStyle: single_quotes

Metrics/BlockLength:
Exclude:
– ‘spec/**/*’
– ‘config/routes.rb’
Example: Conventional Commit Messages
# ✅ Good commit messages
feat: add user authentication with Devise
fix: resolve N+1 query in products index
docs: update README with setup instructions
refactor: extract order processing to service object
test: add integration tests for checkout flow

# ❌ Bad commit messages
fixed stuff
wip
updates
🎯 Team Guidelines Checklist:
• Use RuboCop for consistent code style
• Follow Rails naming conventions strictly
• Document any convention breaks
• Write tests for all new features
• Use conventional commit messages
• Review code for convention compliance

3.4 Code Review Checklist

A comprehensive checklist ensures code reviews focus on both convention compliance and code quality.

🔍 Convention Compliance

  • ✅ Naming: Models singular, controllers plural, tables plural
  • ✅ File locations: Files in correct Rails directories
  • ✅ RESTful actions: Standard CRUD actions used appropriately
  • ✅ Associations: Proper use of belongs_to, has_many, etc.
  • ✅ Validations: Appropriate model validations

🛡️ Security Review

  • 🔐 Strong parameters: Proper use of params.require().permit()
  • 🔐 Authentication: Appropriate before_action filters
  • 🔐 Authorization: Proper access control
  • 🔐 SQL injection: Safe database queries
  • 🔐 XSS protection: Proper escaping in views

⚡ Performance Review

  • 🚀 N+1 queries: Use includes() for associations
  • 🚀 Database indexes: Appropriate indexes on foreign keys
  • 🚀 Caching: Consider caching for expensive operations
  • 🚀 Background jobs: Long-running tasks in background
  • 🚀 Asset optimization: Proper asset compilation

🧪 Testing Review

  • ✅ Unit tests: Model and controller tests
  • ✅ Integration tests: End-to-end feature tests
  • ✅ Test coverage: Adequate test coverage
  • ✅ Test data: Proper use of factories/fixtures
  • ✅ Test naming: Descriptive test names
Example: Code Review Checklist Template
## Code Review Checklist

### Conventions
– [ ] Follows Rails naming conventions
– [ ] Files in correct directories
– [ ] Uses RESTful actions appropriately
– [ ] Proper model associations

### Security
– [ ] Strong parameters used
– [ ] Authentication/authorization checks
– [ ] No SQL injection vulnerabilities
– [ ] XSS protection in place

### Performance
– [ ] No N+1 queries
– [ ] Appropriate database indexes
– [ ] Background jobs for long tasks

### Testing
– [ ] Unit tests written
– [ ] Integration tests written
– [ ] Test coverage adequate
– [ ] Tests are descriptive
🎯 Code Review Best Practices:
• Review for convention compliance first
• Check security implications
• Consider performance impact
• Ensure adequate testing
• Provide constructive feedback
• Approve only when all checks pass

3.5 Performance Considerations

Rails conventions can impact performance. Understanding these considerations helps build fast, scalable applications.

🗄️ Database Performance

  • 📊 N+1 queries: Use includes() and joins() to prevent
  • 📊 Indexing: Add indexes on foreign keys and frequently queried columns
  • 📊 Query optimization: Use select() to limit columns
  • 📊 Pagination: Use pagination for large datasets
  • 📊 Database views: Use views for complex queries

💾 Caching Strategies

  • ⚡ Fragment caching: Cache expensive view fragments
  • ⚡ Russian doll caching: Nested cache keys for complex data
  • ⚡ Action caching: Cache entire controller actions
  • ⚡ Model caching: Cache model instances
  • ⚡ Background jobs: Move slow operations to background

🎯 Code Optimization

  • 🚀 Lazy loading: Load associations only when needed
  • 🚀 Eager loading: Load associations upfront
  • 🚀 Counter caches: Use counter_cache for association counts
  • 🚀 Touch: Use touch: true for cache invalidation
  • 🚀 Batch operations: Use find_each for large datasets
Example: Performance Optimization
# ❌ Bad: N+1 query problem
class ProductsController < ApplicationController
def index
@products = Product.all # Will cause N+1 queries
end
end

# ✅ Good: Optimized with includes
class ProductsController < ApplicationController
def index
@products = Product.includes(:category, :reviews)
.where(active: true)
.order(created_at: :desc)
.page(params[:page])
end
end
Example: Caching Implementation
# app/views/products/index.html.erb
<% cache [“products”, “index”, @products.maximum(:updated_at)] do %>
<h1>Our Products</h1>
<div class=”products-grid”>
<% @products.each do |product| %>
<% cache product do %>
<%= render ‘product_card’, product: product %>
<% end %>
<% end %>
</div>
<% end %>
🎯 Performance Best Practices:
• Always use includes() for associations in loops
• Add database indexes on foreign keys
• Use caching for expensive operations
• Implement pagination for large datasets
• Move slow operations to background jobs
• Monitor performance with tools like Bullet

3.6 Security Best Practices

Rails conventions include many security features, but understanding and properly implementing them is crucial.

🔐 Authentication & Authorization

  • 🛡️ Use established gems: Devise for authentication, CanCanCan/Pundit for authorization
  • 🛡️ Strong parameters: Always use params.require().permit()
  • 🛡️ CSRF protection: Ensure CSRF tokens are included in forms
  • 🛡️ Session security: Configure secure session settings
  • 🛡️ Password hashing: Use bcrypt for password storage

🗄️ Database Security

  • 🔒 SQL injection prevention: Use ActiveRecord methods, not raw SQL
  • 🔒 Input validation: Validate all user inputs
  • 🔒 Data sanitization: Sanitize data before database operations
  • 🔒 Access control: Implement proper database access controls
  • 🔒 Encryption: Encrypt sensitive data at rest

🌐 Web Security

  • 🌍 XSS protection: Use Rails’ built-in XSS protection
  • 🌍 Content Security Policy: Implement CSP headers
  • 🌍 HTTPS enforcement: Force HTTPS in production
  • 🌍 Secure headers: Configure security headers
  • 🌍 Input sanitization: Sanitize all user inputs
Example: Secure Controller Implementation
class UsersController < ApplicationController
before_action :authenticate_user!
before_action :set_user, only: [:show, :edit, :update, :destroy]
before_action :authorize_user!, only: [:edit, :update, :destroy]

def create
@user = User.new(user_params)
if @user.save
redirect_to @user, notice: ‘User created successfully.’
else
render :new, status: :unprocessable_entity
end
end

private

def user_params
params.require(:user).permit(:name, :email, :password, :password_confirmation)
end

def authorize_user!
unless current_user == @user || current_user.admin?
redirect_to root_path, alert: ‘Access denied.’
end
end
end
Example: Secure Model Implementation
class User < ApplicationRecord
has_secure_password

validates :email, presence: true, uniqueness: true,
format: { with: URI::MailTo::EMAIL_REGEXP }
validates :password, length: { minimum: 8 },
format: { with: /\A(?=.*[a-z])(?=.*[A-Z])(?=.*\d)/,
message: ‘must include uppercase, lowercase, and number’ }

before_save :downcase_email

private

def downcase_email
email.downcase! if email.present?
end
end
🎯 Security Best Practices:
• Always use strong parameters
• Implement proper authentication and authorization
• Validate and sanitize all user inputs
• Use HTTPS in production
• Keep gems and Rails updated
• Implement proper error handling
• Use security headers and CSP

4. Bonus Tips with Examples

4.1 Custom Generators

This section provides an example of creating a custom generator.

Example: Custom Generator
rails generate custom_generator
class CustomGenerator < Rails::Generators::NamedBase
source_root File.expand_path(‘templates’, __dir__)
def create_file
# Implementation of the generator
end
end

4.2 Using Concerns

This section provides an example of using concerns in Rails.

Example: Concern
class UserConcern < ApplicationConcern
def self.find_by_name(name)
# Implementation of the concern
end
end

4.3 Service Objects Pattern

This section provides an example of using the Service Objects pattern in Rails.

Example: Service Object
class UserService
def self.find_by_name(name)
# Implementation of the service object
end
end

4.4 Decorators and Presenters

This section provides an example of using decorators and presenters in Rails.

Example: Decorator
class UserDecorator < ApplicationDecorator
def full_name
# Implementation of the decorator
end
end

4.5 Caching Strategies

This section provides an example of using caching strategies in Rails.

Example: Cache
class User < ApplicationRecord
def self.find_by_name(name)
# Implementation of the cache
end
end

4.6 Testing Conventions

This section provides an example of using testing conventions in Rails.

Example: Test
class UserTest < ActiveSupport::TestCase
def test_full_name
# Implementation of the test
end
end

4.7 Deployment Best Practices

This section provides an example of using deployment best practices in Rails.

Example: Deployment
class User < ApplicationRecord
def self.find_by_name(name)
# Implementation of the deployment
end
end

5. Real-World Case Studies

Real-world case studies demonstrate how major companies leverage Rails conventions to build scalable, maintainable applications. These examples show both the benefits of following conventions and the challenges of scaling them.

5.1 Basecamp (37signals)

Basecamp, created by the same team that built Rails, is the ultimate example of Convention Over Configuration in action. As the original Rails application, it demonstrates how conventions scale in a real-world project.

🎯 How Basecamp Uses Conventions

  • ✅ Strict MVC adherence: All business logic in models, presentation in views
  • ✅ RESTful design: Every resource follows REST conventions
  • ✅ Standard naming: Models, controllers, and views follow Rails naming
  • ✅ Conventional associations: Proper use of has_many, belongs_to, etc.

📊 Key Learnings

  • 📈 Scalability: Conventions help manage complexity as the app grows
  • 📈 Team productivity: New developers can contribute immediately
  • 📈 Maintainability: Code remains readable despite feature additions
  • 📈 Performance: Conventions enable predictable optimization
Example: Basecamp’s Project Model
# app/models/project.rb
class Project < ApplicationRecord
belongs_to :account
has_many :messages, dependent: :destroy
has_many :todos, dependent: :destroy
has_many :documents, dependent: :destroy
has_many :people, through: :project_people

validates :name, presence: true
validates :account, presence: true

scope :active, -> { where(archived: false) }
scope :recent, -> { order(updated_at: :desc) }
end
🎯 Basecamp’s Success with Conventions:
• Built by Rails creator DHH and team
• Serves millions of users worldwide
• Maintains high code quality over 15+ years
• Demonstrates conventions work at scale
• Proves conventions enable rapid development

5.2 GitHub

GitHub, the world’s largest code hosting platform, started as a Rails application and demonstrates how conventions can scale to handle massive traffic and complex features.

🚀 GitHub’s Rails Journey

  • 📅 2008: Founded as a Rails application
  • 📅 2010-2015: Scaled Rails to handle millions of users
  • 📅 2015+: Gradually migrated to microservices while keeping Rails conventions
  • 📅 Present: Still uses Rails for many core features

🔧 How GitHub Leveraged Conventions

  • ⚡ RESTful APIs: Built their API following Rails conventions
  • ⚡ Model associations: Complex relationships between repos, users, issues
  • ⚡ Background jobs: Used Rails conventions for Git operations
  • ⚡ Authentication: Built on Rails authentication conventions

📈 Scaling Challenges

  • 🔧 Database scaling: Had to optimize beyond Rails conventions
  • 🔧 Performance: Custom caching strategies needed
  • 🔧 Microservices: Gradually moved away from monolithic Rails
  • 🔧 Custom solutions: Built GitHub-specific conventions
Example: GitHub’s Repository Model
# app/models/repository.rb
class Repository < ApplicationRecord
belongs_to :owner, polymorphic: true
has_many :branches, dependent: :destroy
has_many :commits, dependent: :destroy
has_many :issues, dependent: :destroy
has_many :pull_requests, dependent: :destroy
has_many :collaborators, through: :collaborations

validates :name, presence: true, format: { with: /\A[a-zA-Z0-9._-]+\z/ }
validates :owner, presence: true

scope :public, -> { where(private: false) }
scope :recently_updated, -> { order(updated_at: :desc) }
end
🎯 GitHub’s Lessons:
• Conventions work well for rapid development
• Scaling requires custom optimizations
• Rails conventions provide solid foundation
• Microservices can coexist with Rails
• Custom conventions emerge at scale

5.3 Shopify

Shopify, the e-commerce platform powering millions of online stores, demonstrates how Rails conventions can handle complex business logic and massive scale.

🛒 Shopify’s E-commerce Architecture

  • 🏪 Multi-tenant: Each store is a separate tenant
  • 🏪 Plugin system: Apps and themes follow Rails conventions
  • 🏪 Payment processing: Complex financial operations
  • 🏪 Inventory management: Real-time stock tracking

🔧 Convention Implementation

  • ⚙️ Model conventions: Shop, Product, Order, Customer models
  • ⚙️ Controller patterns: RESTful controllers for all resources
  • ⚙️ View conventions: Liquid templates with Rails helpers
  • ⚙️ Background jobs: Order processing, inventory updates

📊 Scaling Strategies

  • 📈 Database sharding: Custom solutions beyond Rails conventions
  • 📈 Caching layers: Redis and Memcached integration
  • 📈 CDN usage: Asset delivery optimization
  • 📈 Microservices: Gradual migration from monolith
Example: Shopify’s Product Model
# app/models/product.rb
class Product < ApplicationRecord
belongs_to :shop
has_many :variants, dependent: :destroy
has_many :images, as: :imageable, dependent: :destroy
has_many :product_tags, dependent: :destroy
has_many :tags, through: :product_tags
has_many :line_items, through: :variants

validates :title, presence: true
validates :shop, presence: true

scope :active, -> { where(published: true) }
scope :by_shop, ->(shop_id) { where(shop_id: shop_id) }
scope :recent, -> { order(created_at: :desc) }

def available?
published? && variants.any?(&:available?)
end
end
🎯 Shopify’s Success Factors:
• Rails conventions enabled rapid development
• Multi-tenant architecture built on conventions
• Plugin ecosystem leverages Rails patterns
• Performance optimizations built on solid foundation
• Conventions help manage complex business logic

5.4 Airbnb

Airbnb, the global accommodation marketplace, shows how Rails conventions can handle complex booking systems, user management, and international scaling.

🏠 Airbnb’s Platform Architecture

  • 🏡 Booking system: Complex reservation logic
  • 🏡 User management: Hosts and guests with different roles
  • 🏡 Payment processing: International payment handling
  • 🏡 Search and discovery: Advanced filtering and recommendations

🔧 Convention Usage

  • ⚙️ Model relationships: User, Listing, Booking, Review models
  • ⚙️ Controller patterns: RESTful controllers for all resources
  • ⚙️ Background jobs: Email notifications, payment processing
  • ⚙️ API conventions: RESTful API following Rails patterns

🌍 International Scaling

  • 🌐 Multi-language: Rails i18n conventions
  • 🌐 Currency handling: Custom conventions for money
  • 🌐 Time zones: Rails time zone conventions
  • 🌐 Regional compliance: Custom validations and rules
Example: Airbnb’s Booking Model
# app/models/booking.rb
class Booking < ApplicationRecord
belongs_to :guest, class_name: ‘User’
belongs_to :listing
has_one :payment, dependent: :destroy
has_one :review, dependent: :destroy

validates :check_in, presence: true
validates :check_out, presence: true
validates :guests, numericality: { greater_than: 0 }
validate :check_out_after_check_in
validate :no_overlapping_bookings

scope :upcoming, -> { where(‘check_in >= ?’, Date.current) }
scope :past, -> { where(‘check_out < ?', Date.current) }
scope :by_listing, ->(listing_id) { where(listing_id: listing_id) }

def duration
(check_out – check_in).to_i
end

def total_price
listing.price_per_night * duration
end

private

def check_out_after_check_in
return unless check_in && check_out
if check_out <= check_in
errors.add(:check_out, ‘must be after check-in’)
end
end

def no_overlapping_bookings
overlapping = listing.bookings.where(
‘check_in < ? AND check_out > ?’, check_out, check_in
).where.not(id: id)

if overlapping.exists?
errors.add(:base, ‘Dates conflict with existing booking’)
end
end
end
🎯 Airbnb’s Key Insights:
• Rails conventions handle complex business logic
• International scaling requires custom conventions
• Background jobs essential for user experience
• API conventions enable mobile app development
• Conventions help manage regulatory compliance

5.5 Twitter (Early Days)

Twitter’s early days provide a fascinating case study of how Rails conventions can handle rapid growth and the challenges of scaling beyond conventional limits.

🐦 Twitter’s Rails Journey

  • 📅 2006: Started as a simple Rails application
  • 📅 2007-2008: Rapid growth strained Rails conventions
  • 📅 2009-2010: “Fail Whale” era – scaling challenges
  • 📅 2011+: Gradual migration to custom solutions

⚡ Scaling Challenges

  • 🚨 Database bottlenecks: Rails conventions couldn’t handle load
  • 🚨 Real-time updates: Polling wasn’t sufficient
  • 🚨 Timeline generation: Complex queries beyond ActiveRecord
  • 🚨 Message delivery: Background job queues overwhelmed

🔧 Solutions Developed

  • ⚙️ Custom caching: Built specialized caching layers
  • ⚙️ Database optimization: Custom SQL beyond Rails conventions
  • ⚙️ Real-time infrastructure: WebSockets and streaming
  • ⚙️ Service architecture: Broke monolith into services
Example: Twitter’s Tweet Model (Early Days)
# app/models/tweet.rb (Simplified early version)
class Tweet < ApplicationRecord
belongs_to :user
has_many :mentions, dependent: :destroy
has_many :hashtags, through: :tweet_hashtags

validates :content, presence: true, length: { maximum: 140 }
validates :user, presence: true

scope :recent, -> { order(created_at: :desc) }
scope :by_user, ->(user_id) { where(user_id: user_id) }

# This simple approach couldn’t scale
def self.timeline_for(user)
following_ids = user.following.pluck(:id)
where(user_id: following_ids + [user.id])
.includes(:user)
.order(created_at: :desc)
.limit(20)
end
end
🎯 Twitter’s Lessons:
• Rails conventions work well for rapid prototyping
• Extreme scale requires custom solutions
• Conventions provide good starting point
• Real-time features need specialized infrastructure
• Database design critical for performance

5.6 Kickstarter

Kickstarter, the crowdfunding platform, demonstrates how Rails conventions can handle complex project management, payment processing, and community features.

💡 Kickstarter’s Platform Features

  • 🎯 Project management: Campaign creation and management
  • 🎯 Payment processing: Pledge collection and fulfillment
  • 🎯 Community features: Comments, updates, backer rewards
  • 🎯 Analytics: Project performance tracking

🔧 Convention Implementation

  • ⚙️ Model relationships: Project, User, Pledge, Reward models
  • ⚙️ Controller patterns: RESTful controllers for all resources
  • ⚙️ Background jobs: Payment processing, email notifications
  • ⚙️ API conventions: RESTful API for mobile apps

📊 Business Logic Complexity

  • 💼 Funding rules: All-or-nothing funding model
  • 💼 Reward fulfillment: Complex reward management
  • 💼 Payment timing: Charges only on successful funding
  • 💼 Project updates: Creator communication system
Example: Kickstarter’s Project Model
# app/models/project.rb
class Project < ApplicationRecord
belongs_to :creator, class_name: ‘User’
has_many :pledges, dependent: :destroy
has_many :rewards, dependent: :destroy
has_many :updates, dependent: :destroy
has_many :comments, dependent: :destroy
has_many :backers, through: :pledges, source: :user

validates :title, presence: true
validates :description, presence: true
validates :goal_amount, numericality: { greater_than: 0 }
validates :deadline, presence: true
validate :deadline_in_future

scope :active, -> { where(‘deadline > ?’, Time.current) }
scope :successful, -> { where(‘pledged_amount >= goal_amount’) }
scope :trending, -> { order(pledged_amount: :desc) }

def funded?
pledged_amount >= goal_amount
end

def days_remaining
[(deadline – Time.current).to_i / 1.day, 0].max
end

def funding_percentage
return 0 if goal_amount.zero?
(pledged_amount.to_f / goal_amount * 100).round(2)
end

private

def deadline_in_future
return unless deadline
if deadline <= Time.current
errors.add(:deadline, ‘must be in the future’)
end
end
end
🎯 Kickstarter’s Success Factors:
• Rails conventions handle complex business logic
• Background jobs essential for payment processing
• Conventions enable rapid feature development
• API conventions support mobile applications
• Community features built on Rails patterns

📊 Key Takeaways from Real-World Case Studies

  • ✅ Conventions work at scale: All major companies started with Rails conventions
  • ✅ Custom solutions emerge: Companies develop their own conventions over time
  • ✅ Performance optimization: Conventions provide foundation for optimization
  • ✅ Team productivity: Conventions enable rapid development and onboarding
  • ✅ Business logic complexity: Rails conventions handle complex domains well
  • ✅ API development: Conventions support both web and mobile applications

7. Interview Questions & Answers

This section provides comprehensive interview questions and answers about Convention Over Configuration in Rails, organized by difficulty level. These questions help assess understanding of Rails conventions and their practical applications.

7.1 Basic Level Questions

Q1: What is Convention Over Configuration?

Answer:
Convention Over Configuration (CoC) is a software design principle that prioritizes sensible defaults and standard naming conventions over explicit configuration. In Rails, it means that if you follow the standard naming and folder structures, you don’t have to write extra configuration code.

Q2: What are the main Rails naming conventions?

Answer:
• Models: Singular, PascalCase (User, BlogPost)
• Controllers: Plural, PascalCase + Controller (UsersController)
• Tables: Plural, snake_case (users, blog_posts)
• Files: snake_case (user.rb, users_controller.rb)
• Views: snake_case in controller-named folders (users/index.html.erb)

Q3: How does Rails automatically connect models to database tables?

Answer:
Rails uses naming conventions to automatically connect models to tables. For example, the User model automatically connects to the users table. If you need a different table name, you can specify it with self.table_name = ‘custom_table_name’.

Q4: What are the standard RESTful controller actions?

Answer:
The seven standard RESTful actions are:
• index – Display all records
• show – Display single record
• new – Display form for new record
• create – Save new record
• edit – Display form for editing
• update – Save changes to record
• destroy – Delete record

Q5: How do you generate a model with Rails conventions?

Answer:
Use the Rails generator: rails generate model User name:string email:string
This automatically creates:
• Model file: app/models/user.rb
• Migration: db/migrate/xxx_create_users.rb
• Test file: test/models/user_test.rb
• Factory: test/factories/users.rb

7.2 Intermediate Level Questions

Q1: How do Rails conventions help with team development?

Answer:
Rails conventions help teams by:
• Onboarding: New developers can understand code immediately
• Code reviews: Everyone knows what to expect
• Maintenance: Any team member can work on any part
• Documentation: Code structure is self-documenting
• Consistency: Reduces cognitive load and errors

Q2: What happens when you use resources :users in routes?

Answer:
resources :users automatically creates 7 RESTful routes:
• GET /users → users#index
• GET /users/new → users#new
• POST /users → users#create
• GET /users/:id → users#show
• GET /users/:id/edit → users#edit
• PATCH/PUT /users/:id → users#update
• DELETE /users/:id → users#destroy

Q3: How do you handle associations following Rails conventions?

Answer:
Rails associations follow naming conventions:
• belongs_to: Foreign key in this table (user_id)
• has_many: Foreign key in other table
• has_one: One-to-one relationship
• has_many :through: Many-to-many through join table
• Polymorphic: Uses _type and _id columns

Q4: What are the benefits of following Rails conventions for performance?

Answer:
Rails conventions help performance by:
• Predictable queries: Standard naming enables optimization
• Eager loading: includes() works with conventional associations
• Caching: Standard cache keys work automatically
• Indexing: Foreign keys follow naming conventions
• Background jobs: Standard job patterns for slow operations

Q5: How do you customize Rails conventions when needed?

Answer:
You can customize conventions by:
• Table names: self.table_name = ‘custom_name’
• Primary keys: self.primary_key = ‘custom_id’
• Foreign keys: Specify in association (foreign_key: ‘custom_id’)
• Routes: Use custom routes alongside resources
• Controllers: Custom actions beyond RESTful seven

7.3 Advanced Level Questions

Q1: How do Rails conventions relate to the MVC pattern?

Answer:
Rails conventions are tightly coupled with MVC:
• Models: Convention-based naming connects to database tables
• Views: Automatic template resolution based on controller actions
• Controllers: Standard RESTful actions with conventional routing
• Associations: Model relationships follow naming conventions
• Helpers: View helpers follow naming patterns

Q2: What are the trade-offs of breaking Rails conventions?

Answer:
Breaking conventions has trade-offs:
• Pros: Custom solutions for specific needs, performance optimization
• Cons: Increased complexity, harder maintenance, team confusion
• When to break: Performance requirements, security needs, complex business logic
• Best practices: Document decisions, ensure team understanding, test thoroughly

Q3: How do Rails conventions scale in large applications?

Answer:
Rails conventions scale through:
• Namespacing: Organize code with modules and namespaces
• Engines: Modular applications following conventions
• Service objects: Extract complex logic while keeping conventions
• Concerns: Share code across models following conventions
• Custom conventions: Teams develop their own patterns over time

Q4: How do you optimize Rails conventions for performance?

Answer:
Performance optimization with conventions:
• Eager loading: Use includes() to prevent N+1 queries
• Counter caches: Add counter_cache for association counts
• Database indexes: Index foreign keys and frequently queried columns
• Caching: Use Rails caching with conventional cache keys
• Background jobs: Move slow operations to background processing

Q5: How do Rails conventions support API development?

Answer:
Rails conventions support APIs through:
• RESTful design: Standard HTTP methods and status codes
• JSON serialization: Automatic JSON rendering with conventions
• Versioning: Namespace controllers for API versions
• Authentication: Standard authentication patterns
• Documentation: Self-documenting API structure

7.4 Scenario-Based Questions

Q1: You’re building an e-commerce site. How would you structure it using Rails conventions?

Answer:
Models:
• User (customers, admins)
• Product (items for sale)
• Order (purchases)
• OrderItem (line items)
• Category (product categories)

Controllers:
• ProductsController (RESTful CRUD)
• OrdersController (order management)
• UsersController (user management)

Routes:
• resources :products
• resources :orders
• resources :users

Q2: Your team is experiencing N+1 query problems. How do you solve this using Rails conventions?

Answer:
Problem: Loading associated data in loops causes multiple queries
Solution using conventions:
• Product.includes(:category, :reviews) – Eager load associations
• User.joins(:orders).includes(:profile) – Combine joins and includes
• Product.preload(:variants) – Preload specific associations
• Order.eager_load(:items).where(items: { quantity: 1 }) – Eager load with conditions
• Use counter_cache for association counts

Q3: You need to add user authentication to an existing Rails app. How do you do this following conventions?

Answer:
Using Devise (conventional approach):
• gem ‘devise’ – Add to Gemfile
• rails generate devise:install – Install Devise
• rails generate devise User – Generate User model
• rails db:migrate – Run migrations
• Add before_action :authenticate_user! to controllers
• Use current_user helper in views
• Follow Devise’s conventional naming and structure

Q4: Your application is growing and you need to add background job processing. How do you implement this using Rails conventions?

Answer:
Using Active Job with Sidekiq:
• rails generate job ProcessOrder – Generate job class
• Follow naming convention: ProcessOrderJob
• Implement perform method in job class
• Use ProcessOrderJob.perform_later(order) to enqueue
• Configure queue adapter in config/application.rb
• Use queue_as :default for queue assignment
• Follow Rails job conventions for error handling and retries

Q5: You’re building an API for a mobile app. How do you structure this using Rails conventions?

Answer:
API structure following conventions:
• rails generate controller Api::V1::Users – Namespace controllers
• Use respond_to :json in controllers
• Follow RESTful conventions for routes
• Use render json: @user for JSON responses
• Implement jbuilder or active_model_serializers for JSON formatting
• Use conventional HTTP status codes (200, 201, 400, 404, 500)
• Implement authentication using before_action filters

7.5 Coding Challenges

Challenge 1: Create a Blog System

Task: Create a blog system with posts, comments, and users using Rails conventions.

Solution:
# Generate models
rails generate model User name:string email:string
rails generate model Post title:string content:text user:references
rails generate model Comment content:text post:references user:references

# app/models/user.rb
class User < ApplicationRecord
has_many :posts, dependent: :destroy
has_many :comments, dependent: :destroy
validates :name, presence: true
validates :email, presence: true, uniqueness: true
end

# app/models/post.rb
class Post < ApplicationRecord
belongs_to :user
has_many :comments, dependent: :destroy
validates :title, presence: true
validates :content, presence: true
end

# config/routes.rb
Rails.application.routes.draw do
resources :users do
resources :posts, only: [:index, :new, :create]
end
resources :posts, except: [:new, :create] do
resources :comments, only: [:create, :destroy]
end
end

Challenge 2: Optimize Database Queries

Task: Optimize the following controller action to prevent N+1 queries.

Problem Code:
def index
@posts = Post.all
end

Optimized Solution:
def index
@posts = Post.includes(:user, :comments)
.order(created_at: :desc)
.page(params[:page])
end

Challenge 3: Create a Custom Generator

Task: Create a custom Rails generator for generating API controllers.

Solution:
# lib/generators/api_controller/api_controller_generator.rb
class ApiControllerGenerator < Rails::Generators::NamedBase
source_root File.expand_path(‘templates’, __dir__)

def create_api_controller
template ‘api_controller.rb.erb’, “app/controllers/api/v1/#{file_name}_controller.rb”
template ‘api_controller_spec.rb.erb’, “spec/controllers/api/v1/#{file_name}_controller_spec.rb”
end
end

# Usage: rails generate api_controller users

7.6 System Design Questions

Q1: Design a social media platform using Rails conventions

Answer:
Core Models:
• User – Users with profiles
• Post – User posts/content
• Comment – Comments on posts
• Like – User likes/reactions
• Follow – User following relationships

Architecture:
• RESTful controllers for all resources
• Background jobs for notifications
• Caching for frequently accessed data
• API endpoints for mobile apps
• Real-time features with Action Cable

Q2: How would you scale a Rails application beyond conventions?

Answer:
Scaling Strategies:
• Database: Read replicas, sharding, custom queries
• Caching: Redis, Memcached, CDN for assets
• Background Jobs: Sidekiq, Resque for async processing
• Microservices: Break monolith into services
• Load Balancing: Multiple application servers
• Monitoring: Application performance monitoring

Q3: Design an e-commerce system with complex business rules

Answer:
System Components:
• Models: Product, Order, User, Payment, Inventory
• Service Objects: OrderProcessor, PaymentService, InventoryManager
• Background Jobs: Order fulfillment, email notifications
• API: RESTful endpoints for mobile apps
• Security: Authentication, authorization, payment security
• Performance: Caching, database optimization, CDN

Q4: How would you handle internationalization in a Rails app?

Answer:
i18n Implementation:
• Locale files: Use Rails i18n conventions
• Time zones: Configure application timezone
• Currency: Use money gem for currency handling
• Content: Translate views and models
• URLs: Locale-specific routing
• Database: Store translated content in separate tables

Q5: Design a real-time chat application using Rails

Answer:
Architecture:
• Action Cable: WebSocket connections for real-time chat
• Models: User, Room, Message, UserRoom
• Channels: RoomChannel for message broadcasting
• Background Jobs: Message processing, notifications
• Caching: Redis for message history and online users
• API: RESTful endpoints for mobile apps

📋 Interview Preparation Tips

  • ✅ Practice coding: Build small Rails apps following conventions
  • ✅ Understand trade-offs: Know when to break conventions
  • ✅ Study real examples: Look at open source Rails projects
  • ✅ Performance knowledge: Understand N+1 queries and optimization
  • ✅ Security awareness: Know Rails security conventions
  • ✅ Testing practices: Understand Rails testing conventions

8. Terms and Vocabulary

Understanding Rails conventions requires familiarity with specific terminology. This section provides comprehensive definitions of terms commonly used in Rails development and Convention Over Configuration.

8.1 Rails-Specific Terms

🔧 Core Rails Concepts

Convention Over Configuration (CoC)

A software design principle that prioritizes sensible defaults and standard naming conventions over explicit configuration. In Rails, this means following established patterns rather than writing extensive configuration code.

Don’t Repeat Yourself (DRY)

A principle that states every piece of knowledge should have a single, unambiguous representation in a system. Rails conventions help achieve DRY by providing reusable patterns.

Active Record

Rails’ Object-Relational Mapping (ORM) system that connects Ruby objects to database tables. It provides an interface for database operations using conventional naming.

RESTful

Representational State Transfer – a software architectural style that uses standard HTTP methods (GET, POST, PUT, DELETE) to perform operations on resources. Rails conventions follow RESTful principles.

MVC (Model-View-Controller)

An architectural pattern that separates an application into three interconnected components. Rails conventions organize code according to MVC principles with specific naming and folder structures.

📁 Rails File Structure Terms

App Directory

The main application code directory containing models, views, controllers, helpers, mailers, and jobs. Rails conventions organize code into specific subdirectories.

Config Directory

Contains application configuration files including routes, database settings, and environment-specific configurations. Rails conventions determine the structure and naming of these files.

DB Directory

Contains database-related files including migrations, seeds, and schema. Rails conventions govern migration naming and database structure.

🎮 Rails Controller Terms

Strong Parameters

A Rails security feature that explicitly defines which parameters are allowed to be mass-assigned. Uses the params.require().permit() pattern.

Before Action

A controller callback that runs before specific actions. Used for authentication, authorization, and setting up instance variables. Follows Rails naming conventions.

Instance Variables

Variables prefixed with @ that are automatically available in views. Rails conventions use specific naming patterns for these variables.

8.2 Web Development Terms

🌐 HTTP and Web Standards

HTTP Methods

Standard web request methods: GET (read), POST (create), PUT/PATCH (update), DELETE (remove). Rails conventions map these to controller actions automatically.

Status Codes

HTTP response codes indicating request success or failure. Rails conventions use standard codes: 200 (OK), 201 (Created), 400 (Bad Request), 404 (Not Found), 500 (Server Error).

CSRF (Cross-Site Request Forgery)

A web security vulnerability where malicious sites perform actions on behalf of authenticated users. Rails provides built-in CSRF protection using tokens in forms.

XSS (Cross-Site Scripting)

A security vulnerability where malicious scripts are injected into web pages. Rails provides automatic HTML escaping to prevent XSS attacks.

🎨 Frontend and Asset Terms

Asset Pipeline

Rails’ system for organizing and serving JavaScript, CSS, and image files. Uses conventions for file organization and automatic compilation.

ERB (Embedded Ruby)

A templating system that embeds Ruby code in HTML. Rails conventions use .html.erb files for view templates.

Helper Methods

Ruby methods that generate HTML and provide view logic. Rails conventions organize helpers in the app/helpers directory with specific naming patterns.

Partial

A reusable view template that can be rendered within other views. Rails conventions use underscore prefix (_partial.html.erb) and specific rendering patterns.

8.3 Database Terms

🗄️ Database Structure Terms

Migration

A Ruby class that describes changes to the database schema. Rails conventions use timestamped filenames and specific naming patterns for different types of changes.

Schema

The complete structure of the database including tables, columns, indexes, and relationships. Rails automatically generates schema.rb based on migrations.

Foreign Key

A database column that references the primary key of another table. Rails conventions use the pattern model_name_id for foreign keys.

Index

A database structure that improves query performance by creating a lookup table for specific columns. Rails conventions suggest indexing foreign keys and frequently queried columns.

🔍 Query Terms

N+1 Query Problem

A performance issue where loading associated records results in many database queries. Rails provides solutions like includes() and joins() to prevent this.

Eager Loading

Loading associated records in a single query to avoid N+1 problems. Rails provides includes(), preload(), and eager_load() methods.

Scope

A reusable query fragment defined in a model. Rails conventions use lambda syntax and specific naming patterns for scopes.

Validation

Rules that ensure data integrity before saving to the database. Rails provides built-in validators and conventions for defining them in models.

🔄 Association Terms

belongs_to

An Active Record association indicating a one-to-one relationship where this model has a foreign key to another model. Rails conventions determine the foreign key name.

has_many

An Active Record association indicating a one-to-many relationship where another model has a foreign key to this model. Rails conventions determine the associated model name.

has_one

An Active Record association indicating a one-to-one relationship where another model has a foreign key to this model. Similar to has_many but expects only one associated record.

has_many :through

An Active Record association for many-to-many relationships using a join table. Rails conventions determine the join table name and structure.

8.4 Architecture Terms

🏗️ Design Pattern Terms

Service Object

A Ruby class that encapsulates business logic outside of models and controllers. Rails conventions suggest placing service objects in app/services directory.

Concern

A module that allows sharing code across multiple models. Rails conventions use the app/models/concerns directory and specific naming patterns.

Decorator

A design pattern that adds behavior to objects without modifying their class. Rails conventions suggest using gems like Draper or implementing custom decorators.

Presenter

A class that handles the presentation logic for a model, similar to a decorator but focused on view-specific logic. Rails conventions suggest placing presenters in app/presenters.

🔧 Application Architecture Terms

Monolith

A single, large application that contains all functionality. Rails applications typically start as monoliths following conventional structure.

Microservices

An architectural style where an application is built as a collection of small, independent services. Rails can be used to build individual microservices following conventions.

API

Application Programming Interface – a set of rules for building and integrating application software. Rails conventions support building RESTful APIs with standard patterns.

Engine

A Rails application that can be mounted within another Rails application. Engines follow Rails conventions and can be packaged as gems.

⚡ Performance Terms

Caching

Storing frequently accessed data in memory to improve performance. Rails provides multiple caching strategies following conventional patterns.

Background Jobs

Asynchronous processing of tasks outside the web request cycle. Rails provides Active Job framework with conventional job patterns.

Load Balancing

Distributing incoming network traffic across multiple servers. Rails applications can be load balanced while maintaining conventional structure.

Horizontal Scaling

Adding more servers to handle increased load. Rails conventions help maintain consistency across multiple application instances.

8.5 Testing Terms

🧪 Testing Framework Terms

Unit Test

A test that verifies the behavior of a single unit of code (like a model method). Rails conventions organize unit tests in test/models directory.

Integration Test

A test that verifies the interaction between multiple components. Rails conventions organize integration tests in test/integration directory.

System Test

A test that verifies the entire application from a user’s perspective. Rails conventions use Capybara for system tests in test/system directory.

RSpec

A popular testing framework for Ruby that provides a more expressive syntax than Rails’ built-in testing. Follows conventions for test organization and naming.

🔍 Test Data Terms

Fixture

Static test data defined in YAML files. Rails conventions place fixtures in test/fixtures directory with specific naming patterns.

Factory

Dynamic test data created using factory methods. Popular gems like FactoryBot follow Rails conventions for factory organization.

Mock

A test double that simulates the behavior of a real object. Rails testing conventions support mocking through various testing frameworks.

Stub

A test double that provides canned answers to method calls. Used in Rails testing to isolate units under test.

📊 Test Coverage Terms

Code Coverage

The percentage of code that is executed during testing. Rails conventions support coverage tools like SimpleCov.

Test-Driven Development (TDD)

A development methodology where tests are written before the code. Rails conventions support TDD through its testing framework.

Behavior-Driven Development (BDD)

A development methodology that focuses on behavior specification. Rails conventions support BDD through frameworks like RSpec and Cucumber.

8.6 Deployment Terms

🚀 Deployment Platform Terms

Heroku

A cloud platform for deploying Rails applications. Heroku follows Rails conventions and provides automatic detection of Rails apps.

Capistrano

A deployment automation tool for Rails applications. Uses conventional deployment patterns and Rails-specific configurations.

Docker

A containerization platform that packages applications with their dependencies. Rails applications can be containerized while maintaining conventional structure.

Kubernetes

A container orchestration platform for managing containerized applications. Rails applications can be deployed on Kubernetes following conventional patterns.

⚙️ Environment Terms

Development Environment

The local environment where developers write and test code. Rails conventions provide specific configurations for development in config/environments/development.rb.

Production Environment

The live environment where the application serves real users. Rails conventions provide specific configurations for production in config/environments/production.rb.

Staging Environment

A testing environment that mirrors production. Rails conventions support staging configurations in config/environments/staging.rb.

Environment Variables

Configuration values that vary between environments. Rails conventions use the dotenv gem and specific naming patterns for environment variables.

🔧 Server Terms

Web Server

Software that handles HTTP requests and serves web pages. Popular Rails web servers include Puma, Unicorn, and Passenger.

Application Server

Software that runs the Rails application and handles business logic. Rails applications run on application servers following conventional deployment patterns.

Reverse Proxy

A server that sits between clients and application servers, handling tasks like load balancing and SSL termination. Nginx is commonly used with Rails applications.

Load Balancer

A device that distributes incoming network traffic across multiple servers. Rails applications can be load balanced while maintaining conventional structure.

📚 Additional Resources for Learning Rails Terminology

  • 📖 Rails Guides: Official documentation with comprehensive terminology
  • 📖 Rails API Documentation: Detailed method and class references
  • 📖 Rails Community: Forums and discussions about Rails concepts
  • 📖 Rails Blogs: Articles explaining Rails terminology and concepts
  • 📖 Rails Podcasts: Audio content about Rails development

9. Common Mistakes and How to Avoid Them

Even experienced Rails developers make mistakes when working with conventions. This section identifies common pitfalls and provides practical solutions to avoid them.

9.1 Naming Convention Mistakes

❌ Mistake 1: Inconsistent Model Naming

❌ Wrong:
class Users < ApplicationRecord # Should be singular
class blog_post < ApplicationRecord # Should be PascalCase
class UserProfile < ApplicationRecord # Should be UserProfile

✅ Correct:
class User < ApplicationRecord
class BlogPost < ApplicationRecord
class UserProfile < ApplicationRecord

❌ Mistake 2: Wrong Controller Naming

❌ Wrong:
class UserController < ApplicationController # Missing 's'
class users_controller < ApplicationController # Wrong case

✅ Correct:
class UsersController < ApplicationController
# File: app/controllers/users_controller.rb

❌ Mistake 3: Incorrect Table Naming

❌ Wrong:
create_table :user do |t| # Should be plural
create_table :blog_posts do |t| # Correct

✅ Correct:
create_table :users do |t|
create_table :blog_posts do |t|

❌ Mistake 4: Wrong File Locations

❌ Wrong:
# app/models/user.rb (correct)
# app/controllers/user_controller.rb (wrong – should be users_controller.rb)
# app/views/user/index.html.erb (wrong – should be users/index.html.erb)

✅ Correct:
# app/models/user.rb
# app/controllers/users_controller.rb
# app/views/users/index.html.erb
🎯 How to Avoid Naming Mistakes:
• Use Rails generators to create files with correct naming
• Follow the pattern: Model (singular) → Controller (plural) → Views (plural)
• Use PascalCase for class names, snake_case for files
• Always use plural for table names and controller names
• Double-check file locations match Rails conventions

9.2 Structure Mistakes

❌ Mistake 1: Wrong Folder Structure

❌ Wrong:
app/
├── models/
│ └── user.rb
├── controllers/
│ └── user_controller.rb # Wrong name
└── views/
└── user/ # Wrong folder name
└── index.html.erb

✅ Correct:
app/
├── models/
│ └── user.rb
├── controllers/
│ └── users_controller.rb
└── views/
└── users/
└── index.html.erb

❌ Mistake 2: Missing RESTful Actions

❌ Wrong:
class UsersController < ApplicationController
def list # Non-standard action name
@users = User.all
end

def display # Non-standard action name
@user = User.find(params[:id])
end

✅ Correct:
class UsersController < ApplicationController
def index # Standard RESTful action
@users = User.all
end

def show # Standard RESTful action
@user = User.find(params[:id])
end

❌ Mistake 3: Incorrect Route Structure

❌ Wrong:
get ‘/users’, to: ‘users#list’ # Non-standard route
get ‘/users/:id’, to: ‘users#display’ # Non-standard route

✅ Correct:
resources :users # Creates all 7 RESTful routes
# Or explicitly:
get ‘/users’, to: ‘users#index’
get ‘/users/:id’, to: ‘users#show’

❌ Mistake 4: Wrong Model Associations

❌ Wrong:
class User < ApplicationRecord
has_many :posts, foreign_key: ‘author_id’ # Wrong if table uses user_id
belongs_to :profile, class_name: ‘UserProfile’ # Wrong if it’s has_one

✅ Correct:
class User < ApplicationRecord
has_many :posts # Rails assumes user_id foreign key
has_one :profile # For one-to-one relationship
🎯 How to Avoid Structure Mistakes:
• Use Rails generators to create proper structure
• Follow RESTful conventions for controller actions
• Use resources :model_name for standard routes
• Understand the difference between has_one and belongs_to
• Keep files in their conventional locations

9.3 Performance Mistakes

❌ Mistake 1: N+1 Query Problems

❌ Wrong:
def index
@users = User.all # Will cause N+1 queries in view
end

# In view:
<% @users.each do |user| %>
<%= user.profile.name %> # N+1 query here
<% end %>

✅ Correct:
def index
@users = User.includes(:profile).all
end

❌ Mistake 2: Missing Database Indexes

❌ Wrong:
class CreateUsers < ActiveRecord::Migration[7.0]
def change
create_table :users do |t|
t.string :email
t.references :role # No index on foreign key
t.timestamps
end
end
end

✅ Correct:
class CreateUsers < ActiveRecord::Migration[7.0]
def change
create_table :users do |t|
t.string :email
t.references :role, null: false, foreign_key: true, index: true
t.timestamps
end

add_index :users, :email, unique: true
end
end

❌ Mistake 3: Not Using Counter Caches

❌ Wrong:
class User < ApplicationRecord
has_many :posts
end

# In view:
<%= user.posts.count %> # Executes COUNT query

✅ Correct:
class User < ApplicationRecord
has_many :posts, counter_cache: true
end

# Add posts_count column to users table
# In view:
<%= user.posts_count %> # Uses cached count

❌ Mistake 4: Not Using Background Jobs

❌ Wrong:
def create
@user = User.new(user_params)
if @user.save
# Slow operations in controller
send_welcome_email(@user) # Blocks response
generate_user_profile(@user) # Blocks response
redirect_to @user
end
end

✅ Correct:
def create
@user = User.new(user_params)
if @user.save
# Move slow operations to background
UserSetupJob.perform_later(@user.id)
redirect_to @user
end
end
🎯 How to Avoid Performance Mistakes:
• Always use includes() when accessing associations in loops
• Add indexes on foreign keys and frequently queried columns
• Use counter_cache for association counts
• Move slow operations to background jobs
• Monitor performance with tools like Bullet gem

9.4 Security Mistakes

❌ Mistake 1: Not Using Strong Parameters

❌ Wrong:
def create
@user = User.new(params[:user]) # Mass assignment vulnerability
if @user.save
redirect_to @user
end
end

✅ Correct:
def create
@user = User.new(user_params)
if @user.save
redirect_to @user
end
end

private

def user_params
params.require(:user).permit(:name, :email, :password)
end

❌ Mistake 2: Missing Authentication

❌ Wrong:
class UsersController < ApplicationController
def edit
@user = User.find(params[:id])
# Anyone can edit any user
end

✅ Correct:
class UsersController < ApplicationController
before_action :authenticate_user!
before_action :authorize_user!

def edit
@user = User.find(params[:id])
end

private

def authorize_user!
unless current_user == @user || current_user.admin?
redirect_to root_path, alert: ‘Access denied.’
end
end
end

❌ Mistake 3: SQL Injection Vulnerabilities

❌ Wrong:
def search
query = params[:q]
@users = User.where(“name LIKE ‘%#{query}%'”) # SQL injection
end

✅ Correct:
def search
query = params[:q]
@users = User.where(“name LIKE ?”, “%#{query}%”) # Safe
# Or even better:
@users = User.where(“name ILIKE ?”, “%#{query}%”)
end

❌ Mistake 4: Not Validating User Input

❌ Wrong:
class User < ApplicationRecord
# No validations
end

✅ Correct:
class User < ApplicationRecord
validates :name, presence: true, length: { minimum: 2 }
validates :email, presence: true, uniqueness: true,
format: { with: URI::MailTo::EMAIL_REGEXP }
validates :password, length: { minimum: 8 },
format: { with: /\A(?=.*[a-z])(?=.*[A-Z])(?=.*\d)/,
message: ‘must include uppercase, lowercase, and number’ }
end
🎯 How to Avoid Security Mistakes:
• Always use strong parameters for mass assignment
• Implement proper authentication and authorization
• Use parameterized queries to prevent SQL injection
• Validate all user inputs
• Keep gems and Rails updated
• Use HTTPS in production

📋 Summary: Key Points to Remember

  • ✅ Naming: Follow Rails naming conventions strictly
  • ✅ Structure: Use Rails generators and keep files in correct locations
  • ✅ Performance: Use includes(), add indexes, and use background jobs
  • ✅ Security: Use strong parameters, validate input, and implement authentication
  • ✅ Testing: Test edge cases, write integration tests, and use proper test data

Learn more about Rails

51 thoughts on “Convention Over Configuration in Rails – Complete Guide with Examples”

Comments are closed.

Scroll to Top