Hey everyone — Sajjad Umar here with the June edition of Ruby on Rails Monthly!
As we reach the year's midpoint, the Rails ecosystem continues its impressive momentum with critical security updates, database enhancements, and exciting community events. This month brings us smarter Active Job handling, important Trix vulnerability patches, and new cache control capabilities - all while the Rails team prepares for the historic final RailsConf. Let's explore what's been shaping the Rails landscape these past weeks!
I've tried a new format for this newsletter! Tell me in the comments: does this work better for you?
Our Proud Partners
rubyonrails.pk - for the love of rails in Pakistan
adex.world - Free cross-promotion platform
Rails Foundation Announcement
The Rails Foundation confirmed that Rails World 2025 sessions will be recorded and published on YouTube:
Opening/Closing keynotes available immediately
All other sessions published shortly after
Watch recordings here
Community Guides Needing Your Input
Three documentation improvements are open for community review:
Active Record Encryption Guide Refresh
Review PR #55188
Help refine Rails' built-in encryption documentation - particularly valuable for developers working with sensitive dataThreading & Code Execution Guide Update
Contribute to PR #55179
Perfect opportunity if you have experience with concurrent Rails applications or background processingPostgreSQL Guide Consolidation
Join discussion on PR #55135
Help merge API docs with usage guides for better Postgres navigation
Why participate? Your review ensures these resources stay accurate for the entire community!
Final RailsConf Announcement
The last RailsConf (July 8-10, Philadelphia) will feature:
Fireside chat with DHH
Talks by Rails core team members including Eileen Uchitelle (Core), Gannon McGibbon (Committers), Hartley McGuire (Issues), and Matheus Richard (Triage)
Discussions on Rails' future direction
Tickets remain available for this historic event.
Conference Details
SQLite Adapter Precision Fix
PR #55180 brings accurate row counting to SQLite:
# Before: Inconsistent counts
User.where(active: true).update_all(status: :verified)
# => Might report incorrect numbers due to cascading deletes
# After: Precise affected rows
User.where(active: true).update_all(status: :verified)
# => Returns exact count of modified records
Key improvements:
Fixes overcounting from cascading operations
Eliminates false positives on read-only queries
Uses SQLite's native counters more intelligently
Affects all SQLite users - especially important for audit trails
Unified Transaction Isolation Control
PR #55176 simplifies isolation management:
# New streamlined approach
ActiveRecord.with_transaction_isolation_level(:serializable) do
Shard1.connection.transaction { ... }
Shard2.connection.transaction { ... }
end
# Old method: Manual per-connection setup
[Shard1, Shard2].each do |shard|
shard.connection_pool.with_connection do |conn|
conn.transaction(isolation: :serializable) { ... }
end
end
Why this matters:
Single declaration for all databases/shards
Eliminates connection pool iteration
40% less boilerplate in multi-db transactions
Works seamlessly with transactional tests
Essential for financial systems and multi-tenant applications
Active Job Continuations Upgrade
PR #55174 enhances pausable jobs:
class DataExportJob < ApplicationJob
include ActiveJob::Continuations
def perform
checkpoint :extract_data, retry: :exponential
checkpoint :transform, retry: [3, 5.minutes]
checkpoint :load_to_warehouse
end
end
Key improvements:
Timing adjustment: Checkpoints now execute before job steps
New instrumentation: Runtime metrics for each checkpoint
Transaction safety: Automatic detection of checkpoint-in-transaction anti-pattern
Order validation: Ensures step consistency during job resumption
Configurable retries: Per-checkpoint retry strategies
Critical for ETL pipelines and long-running background tasks
PostgreSQL Documentation Restructuring
The PostgreSQL-specific guide has been integrated into Rails' core API documentation. This change helps developers by:
Removing database-specific details from general Active Record guides
Centralizing PostgreSQL reference material for easier lookup
Making room for future database adapters in the documentation structure
Implementation details in PR #55135
Active Job Continuations Refinements
Building on last month's pausable jobs feature, this update addresses edge cases discovered during real-world use:
Added safety checks to prevent job resumption in inconsistent states
Fixed race conditions during multi-step job execution
Improved error messages for failed checkpoint transitions
Follow-up PR #55151
Action Text Upload Progress Accuracy
File upload progress bars now reflect server-side processing time. Previously, progress indicators would stall at 100% during server processing. The update:
Adds hidden timing instrumentation to Trix uploads
Calculates backend processing time estimates
Provides smoother progress bar animation
Technical solution in PR #55157
Current Attributes Leak Fix
Fixed a subtle memory leak where Current
attributes could persist between requests. This could cause:
User A seeing User B's attributes in multi-tenant apps
Accumulating memory in long-running processes
Security concerns with sensitive data
The patch ensures complete attribute reset after each request.
Critical fix in PR #55139
Minitest Plugin Compatibility
Resolved conflicts with test plugins like minitest-focus by changing test loading order:
Test files now load before plugins initialize
Maintains plugin functionality while preventing overrides
Solves "focus tag ignored" issues reported by users
Compatibility fix in PR #55140
CI Optimization
Eliminated duplicate test runs in GitHub Actions:
Separated unit tests from system tests
Reduces CI time by ~18 minutes per run
Lowers resource consumption for Rails maintainers
Workflow change in PR #55136
HEAD Request Compliance
Fixed Rack::Lint violations to meet RFC9110 standards:
HEAD requests now return empty bodies during errors
Resolves compatibility issues with Rack 3+
Ensures proper behavior in API-only applications
Spec compliance in PR #55149
Job Retry Consistency
Preserves original job attributes during retries:
Maintains initial scheduled time instead of resetting
Retains original queue name and priority settings
Prevents unexpected behavior in job monitoring tools
Behavior fix in PR #55141
Active Job Continuations Introduction
PR #55127 adds pausable/resumable jobs:
class DataImportJob
include ActiveJob::Continuable
def perform(import_id)
@import = Import.find(import_id)
step :initialize do
@import.prepare # Runs immediately
end
step :process do |step|
@import.records.find_each(start: step.cursor) do |record|
record.transform
step.advance!(from: record.id) # Saves progress
end
end
step :finalize # Method-based step
end
private
def finalize
@import.cleanup # Runs after resumption
end
end
Key benefits:
Survives server restarts during long jobs
Automatic progress saving between steps
Works with any queuing backend
GitHub Actions Optimization
PR #55120 simplifies CI configuration by removing redundant ruby-version
input - the setup-ruby action now automatically detects .ruby-version
files.
Reflection Cache Performance
PR #55115 boosts association performance by memoizing reflection validations. Since associations can't change after definition, this:
Eliminates redundant metadata checks
Speeds up model initialization
Particularly benefits apps with complex relational mappings
Rails DOM Testing 2.3.0
New release adds:
assert_not_dom expected, actual
# Equivalent to: assert_not_equal expected, actual
Use case:
Verifies DOM elements are absent
Improves integration test readability
Complements existing
assert_dom
helper
Documentation Clarification: Polymorphic :through
Restriction
Rails now explicitly documents that polymorphic associations cannot be used with :through
. This restriction exists because polymorphic associations rely on dual-column references (_id
+ _type
), while :through
assumes single-column foreign keys. Attempting this pattern already raised errors, but the exception was previously undocumented.
Implementation details in PR #55107
Deprecation Notice: :class_name
in Polymorphic belongs_to
Using :class_name
with polymorphic belongs_to
is now deprecated (scheduled for removal in Rails 8.1). The _type
column already stores the associated class name, making this option redundant and potentially misleading.
Deprecation rationale in PR #55091
# DEPRECATED (remove class_name):
belongs_to :reviewable, polymorphic: true, class_name: "Product"
# CORRECT:
belongs_to :reviewable, polymorphic: true
Enhanced Database Control: Namespaced db:migrate:reset
This PR introduces database-specific reset commands for multi-DB setups. This prevents accidental full-database resets in production and enables targeted schema management.
Command implementation in PR #55077
# Resets ONLY primary database:
bin/rails db:migrate:reset:primary
# Resets animals database:
bin/rails db:migrate:reset:animals
Schema Loading Fix: SCHEMA_FORMAT
Consistency
The db:schema:load
command now correctly respects ENV["SCHEMA_FORMAT"]
in Rails 7.2. This fixes CI/CD workflows where schema format differs between environments by allowing runtime overrides of config.active_record.schema_format
.
Behavior fix in PR #55059
# Load SQL structure:
SCHEMA_FORMAT=sql bin/rails db:schema:load
# Load Ruby schema:
SCHEMA_FORMAT=ruby bin/rails db:schema:load
Database Operation Insights
PR #55060 introduces affected_rows
for SQL operations:
result = ActiveRecord::Base.connection.exec_query("
UPDATE posts SET status = 'published'
WHERE created_at < NOW() - INTERVAL '1 year'
")
result.affected_rows # => 342
Use cases:
Verify batch operation impact
Audit log reporting
Performance monitoring
Action Text Maintenance Improvements
Trix Extraction
PR #55058 migrates Trix to standalone gem:
Faster security updates independent of Rails releases
Simplified maintenance for core team
No application changes required
Security Update
PR #55046 addresses CVE-2025-46812 in Trix 2.1.15:
Critical: XSS vulnerability in rich text sanitization
Action required: Update via
bundle update actiontext
Ruby 3.5 Compatibility
PR #55037 optimizes CGI handling:
Loads only
cgi/escape
instead of full gemEliminates deprecation warnings
Maintains functionality as Ruby retires stdlib CGI
HTTP Cache Control Directives
PR #55033 implements RFC-9111 support:
# Check client cache directives
if request.cache_control_directives.max_stale?
serve_stale_content
elsif request.cache_control_directives.no_cache?
force_fresh_response
end
New directives available:
only_if_cached?
- Client accepts stale contentmax_stale?
- Permits expired responsesmin_fresh
- Requires minimum freshness durationno_cache?
- Forces revalidation
Sharpen Your Rails Skills This Summer
As we wrap up this edition, I want to extend a special opportunity for those looking to deepen their Rails expertise. My book "Ruby on Rails for Agile Web Development" is now available with a 30% summer discount - perfect for your seasonal learning goals!
Why this book belongs in your toolkit:
Master Agile patterns specifically for Rails environments
Practical techniques for rapid feature development
Real-world refactoring strategies from monolithic to modular
Exclusive content on Hotwire optimization
Limited-time offer: Use code SUMMER30 at checkout for instant savings:
Get Your Discounted Copy
Until next month, keep building extraordinary things with Rails! The community thrives when we share knowledge and grow together.
Sajjad Umar
Founder, Ruby on Rails Monthly
Share this newsletter with a colleague