What Is New in Ruby on Rails 6.1
| Category | Highlights |
|---|---|
| New Features | Per-database connection switching, Horizontal sharding, Strict loading associations, Delegated types, Async destroy of associations |
| Improvements | Where.not now generates NAND predicates, Scope-leakage fixes in create and named scopes, MySQL uniqueness respects collation, ActionView preload_links_header, ActiveModel errors become objects |
| Breaking Changes | Set config.active_record.legacy_connection_handling = false to use new connection handling, Removal of many deprecated rake tasks and ActionCable/ActionPack methods, ActiveStorage requires new Blob.service_name column migration |
| Deprecations | ActiveRecord::Base.update_attributes, config.active_job.return_false_on_aborted_enqueue, ActionView::Template#refresh, ActiveSupport::Multibyte::Unicode.default_normalization_form, and numerous other helpers |
How does Rails 6.1 improve database connection handling and sharding?
Rails 6.1 introduces per-database connection switching and native horizontal sharding support.
- Set
config.active_record.legacy_connection_handling = falseto enable the new API. - Use
connected_toon an abstract class to switch only the desired database role. - Horizontal sharding is now possible because a model can have separate connections per role.
class ReportingBase < ApplicationRecord
self.abstract_class = true
connects_to database: { writing: :primary, reading: :primary_replica }
end
ReportingBase.connected_to(role: :reading) do
# All queries inside this block use the replica only
end
How can I prevent N+1 queries with the new strict loading feature?
Strict loading forces all associations to be eager-loaded, raising an error if a lazy load occurs.
- Enable globally with
ActiveRecord::Base.strict_loading!or per-model withstrict_loading!. - When a lazy load is attempted, Rails raises
ActiveRecord::StrictLoadingViolationError, letting you catch N+1 problems early.
# Enable strict loading for the whole app
ActiveRecord::Base.strict_loading!
user = User.first # raises if any association is not preloaded
What options does Rails 6.1 give for model inheritance and background destruction?
Delegated types replace STI for concrete super-classes, and destroy associations can now be queued to a background job.
- Delegated types let the superclass have its own table while each subclass lives in a separate table.
- Use
dependent: :destroy_asyncto offload heavy deletions to Active Job.
class Vehicle < ApplicationRecord
delegated_type :vehicle_type, types: %w[Car Truck], dependent: :destroy
end
class Car < ApplicationRecord; end
class Truck < ApplicationRecord; end
class Post < ApplicationRecord
has_many :comments, dependent: :destroy_async
end
What query behavior changes should I be aware of in Active Record 6.1?
Where.not now generates NAND predicates, and scope-leakage bugs have been fixed.
where.notproducesNOT (cond1 AND cond2)instead of separate!=clauses.- Creating records inside a scoped
createblock no longer leaks the scope to class-level queries. - Named scopes no longer inherit the caller's scope, preventing accidental double-filtering.
User.where.not(name: "Jon", role: "admin")
# => SELECT ... WHERE NOT (name = 'Jon' AND role = 'admin')
What are the notable updates to Action View, Active Storage and Active Model errors?
Action View now requires a compiled method container, preload link headers can be disabled, Active Storage adds a new upload API, and Active Model errors are objects.
- ActionView subclasses must implement
#compiled_method_container. - Set
config.action_view.preload_links_header = falseto stop automaticLinkheaders. - ActiveStorage introduces
Blob.create_and_uploadand aservice_namecolumn (run the migration generated byrails app:update). - Model errors are now instances of
ActiveModel::Errorswith a queryable API.
Frequently Asked Questions
Does upgrading to Rails 6.1 require changes to database configuration?
You must set config.active_record.legacy_connection_handling = false and adjust any custom connected_to calls accordingly.
How do I enable strict loading in an existing Rails app?
Add ActiveRecord::Base.strict_loading! to an initializer or call strict_loading! on individual models.
Can I still use the old connection handling APIs after setting legacy_connection_handling to false?
No, the old connection_handlers accessor is removed when legacy handling is disabled.
What is the recommended way to migrate ActiveStorage after upgrading to 6.1?
Run bin/rails app:update to generate a migration that adds the service_name column to the blobs table.
Are there any performance impacts when using delegated types instead of STI?
Delegated types add a small join to fetch subclass tables but avoid the single-table bloat and can improve query clarity.
How do I silence the new deprecation warnings for removed rake tasks?
Remove the tasks from your Rakefile or replace them with the recommended alternatives; no runtime flag exists.