Ruby on Rails Coding Mistakes Every Developer Should Avoid
π« Ruby on Rails Coding Mistakes Every Developer Should Avoid π¦
Ruby on Rails is an amazing framework β it lets you build powerful web applications quickly and elegantly. But even seasoned Rails developers often fall into common traps that lead to performance bottlenecks, maintenance nightmares, and bugs that hide in plain sight π¬.
In this blog, weβll explore the most common Rails coding mistakes developers make, along with real examples, fixes, and checkpoints you can use in your Merge Requests (MRs) β .
π§© 1. Ignoring N+1 Query Problems
β The Mistake:
Developers often loop through ActiveRecord relations without realizing how many database queries are triggered.
# BAD
@users = User.all
@users.each do |user|
puts user.posts.count
end
This runs 1 query for users + N queries for posts, leading to performance disaster π¨.
β The Fix:
Use includes
or eager_load
to preload associations efficiently.
# GOOD
@users = User.includes(:posts)
@users.each do |user|
puts user.posts.count
end
Checkpoint for MR β :
- Did you check for possible N+1 queries using
bullet
gem or logs? - Are you preloading related data where needed?
π§ 2. Fat Models & Skinny Controllers Gone Wrong
β The Mistake:
Developers often stuff too much business logic into models, turning them into βGod Objectsβ.
# BAD
class User < ApplicationRecord
def self.generate_monthly_report
# Complex report generation logic here
end
end
β The Fix:
Move such logic to Service Objects or Interactors.
# GOOD
class MonthlyReportGenerator
def self.call
# clean logic here
end
end
Checkpoint for MR β :
- Are models and controllers under 150 lines?
- Is there business logic that should live in a service class?
π§΅ 3. Missing Background Jobs for Heavy Tasks
β The Mistake:
Running heavy or long-running tasks (like sending emails or processing files) in controllers.
# BAD
def create
UserMailer.welcome_email(@user).deliver_now
end
β The Fix:
Offload such tasks using ActiveJob or Sidekiq.
# GOOD
def create
UserMailer.welcome_email(@user).deliver_later
end
Checkpoint for MR β :
- Are time-consuming operations offloaded to background jobs?
- Did you ensure retries and job uniqueness where applicable?
π§± 4. Overusing Callbacks in Models
β The Mistake:
Callbacks like after_save
, before_create
look convenient, but they often lead to hidden side effects and unpredictable behavior.
# BAD
after_save :send_welcome_email
β The Fix:
Use observers or service classes for side effects. Keep models focused only on persistence logic.
# GOOD
UserCreator.new(user_params).call
Checkpoint for MR β :
- Are callbacks minimal and clearly justified?
- Can side effects be extracted into separate services?
πͺ 5. Skipping Validations & Error Handling
β The Mistake:
Relying on frontend or assumptions instead of ActiveRecord validations.
# BAD
user = User.create(name: nil) # silently fails or causes issues later
β The Fix:
Always validate crucial fields and handle exceptions.
# GOOD
class User < ApplicationRecord
validates :name, presence: true
end
Checkpoint for MR β :
- Are all critical fields validated?
- Is there rescue logic for possible database or API errors?
πΈοΈ 6. Not Using Scopes & Query Objects
β The Mistake:
Hardcoding query logic throughout your controllers or views.
# BAD
@active_users = User.where(active: true).order(created_at: :desc)
β The Fix:
Use named scopes for cleaner, reusable code.
# GOOD
class User < ApplicationRecord
scope :active, -> { where(active: true).order(created_at: :desc) }
end
Checkpoint for MR β :
- Are repeated queries refactored into scopes or Query Objects?
- Is the query logic reusable and DRY?
π¬ 7. Not Leveraging Rails Conventions
β The Mistake:
Over-customizing naming, routes, or folder structures.
# BAD
get '/show_user_profile', to: 'profiles#show'
β The Fix:
Stick to Rails conventions unless you have a strong reason to deviate.
# GOOD
resources :profiles, only: [:show]
Checkpoint for MR β :
- Does the code follow Rails naming conventions?
- Are routes RESTful and minimal?
πΎ 8. Not Indexing Frequently Queried Columns
β The Mistake:
Forgetting to add indexes leads to slow queries and poor scalability.
# BAD
add_index :users, :email, unique: true unless needed
β The Fix:
Index columns used in where
, joins
, or order
clauses.
# GOOD
add_index :users, :email
add_index :posts, :user_id
Checkpoint for MR β :
- Are necessary database indexes present?
- Have you analyzed query performance (EXPLAIN plan)?
π 9. Ignoring Security Best Practices
β The Mistake:
Interpolating parameters directly into queries or views.
# BAD
User.where("email = '#{params[:email]}'")
β The Fix:
Use Railsβ built-in protections.
# GOOD
User.where(email: params[:email])
And always use sanitize
, html_safe
, and strong_parameters
carefully. π‘οΈ
Checkpoint for MR β :
- Are all parameters sanitized and validated?
- No direct SQL or unsafe HTML interpolation?
βοΈ 10. Missing Tests & Linters
β The Mistake:
Relying only on manual testing or skipping code quality tools.
β The Fix:
Use:
- RSpec / Minitest for testing
- Rubocop for linting
- Brakeman for security scans
- SimpleCov for test coverage
Checkpoint for MR β :
- Did you run Rubocop and fix warnings?
- Is the test coverage above the project minimum?
π§ Bonus: Your Merge Request (MR) Checklist π§Ύ
Hereβs a summarized MR checklist to keep your Rails code clean & professional: β Code follows Rails conventions β No N+1 queries (check with Bullet) β Proper validations added β Background jobs for heavy tasks β Business logic in services, not models β Security checks passed β Tests & linters run successfully β Code reviewed for readability & reusability
π‘ Final Thought
Writing Rails code is not just about making things work β itβs about making them maintainable, scalable, and secure. π The real craftsmanship lies in writing code that another developer can read, understand, and extend effortlessly.
βClean code always looks like it was written by someone who cares.β β Robert C. Martin β¨
So, next time you raise that MR, pause for a quick checklist review β your teammates (and future self) will thank you! π
© Lakhveer Singh Rajput - Blogs. All Rights Reserved.