Ruby on Rails Magical Optimization
π Ruby on Rails Magic: 7 Tricky & Unique Optimizations to Supercharge Your Code! οΏ½
Ruby on Rails is a powerful framework, but mastering its hidden tricks can take your code from good to blazing fast! β‘ Below are 7 unique optimizations with examples to make your Rails app leaner, meaner, and more efficient.
1. ** #find_each
**Instead of #each
for Large Queries
Fetching thousands of records with #each
loads everything into memory at once! Instead, use #find_each
, which batches records (default: 1000 at a time).
# β Slower & Memory-Heavy
User.each { |user| process_user(user) }
# β
Optimized
User.find_each { |user| process_user(user) }
Why?
β Reduces memory overhead by loading records in batches.
2. ** #pluck
**Over #select
When You Only Need Specific Columns
If you only need certain columns, #pluck
fetches them directly from the DB, skipping ActiveRecord object creation.
# β Inefficient (creates full objects)
User.where(active: true).select(:id, :name).each { |u| puts u.name }
# β
Faster (only retrieves data)
User.where(active: true).pluck(:id, :name).each { |id, name| puts name }
Why?
β Avoids unnecessary object instantiation.
3. ** #exists?
**Instead of #any?
for Checking Presence
Need to check if any records match a condition? #exists?
is optimized for this and runs a lean SQL query.
# β Executes a full query
if User.where(admin: true).any?
# do something
end
# β
Faster check
if User.where(admin: true).exists?
# do something
end
Why?
β #exists?
stops after finding one match, while #any?
loads all records.
4. ** #update_all
**for Bulk Updates Without Callbacks
Updating multiple records one by one triggers callbacks (slowing things down). Use #update_all
for direct SQL updates.
# β Slow (runs callbacks per record)
User.where(expired: true).each { |u| u.update(active: false) }
# β
Blazing fast (single SQL query)
User.where(expired: true).update_all(active: false)
Why?
β Skips validations & callbacks, executes a single UPDATE query.
5. ** #includes
+ #joins
**for Avoiding N+1 Queries
Combining #includes
(eager loading) with #joins
(filtering) prevents N+1 queries while keeping conditions efficient.
# β N+1 query problem
posts = Post.limit(10)
posts.each { |post| puts post.user.name } # Queries User each time!
# β
Optimized (eager loads users)
posts = Post.includes(:user).limit(10)
posts.each { |post| puts post.user.name } # No extra queries!
# β
Even better with filtering
Post.includes(:user).joins(:user).where(users: { active: true })
Why?
β Prevents multiple DB hits by loading associations upfront.
6. ** #transaction
**for Batch Operations (Atomicity & Speed)
Wrap multiple DB operations in a transaction to speed them up and ensure atomicity (all succeed or none do).
# β Each save hits DB separately
users.each { |user| user.update!(points: 100) }
# β
Single transaction (faster + safer)
User.transaction do
users.each { |user| user.update!(points: 100) }
end
Why?
β Reduces DB roundtrips and ensures data consistency.
7. ** #cache_key
**for Smart Fragment Caching
Railsβ #cache_key
auto-generates a unique key based on model attributes + timestamps, perfect for auto-expiring caches.
# β Hard-coded cache key (risky)
Rails.cache.fetch("user_#{user.id}_profile") { user.profile_data }
# β
Dynamic & auto-expiring
Rails.cache.fetch(user.cache_key) { user.profile_data }
Why?
β Cache auto-invalidates when the record updates.
π‘ Bonus Tip: Use #explain
to Debug Slow Queries
Stuck with a slow query? Run .explain
to see how Rails executes it and spot bottlenecks!
User.where(active: true).order(:created_at).explain
# => Outputs SQL execution plan
π₯ Final Thoughts
These optimizations can drastically improve your Rails appβs performance! Try them out and watch your queries fly. π
Which trick was your favorite? Let me know in the comments! π
#RubyOnRails #Performance #Optimization #WebDev #CodingTips
© Lakhveer Singh Rajput - Blogs. All Rights Reserved.