Action Cable
-
The Action Cable client now ensures successful channel subscriptions:
- The client maintains a set of pending subscriptions until either
the server confirms the subscription or the channel is torn down. - Rectifies the race condition where an unsubscribe is rapidly followed
by a subscribe (on the same channel identifier) and the requests are
handled out of order by the ActionCable server, thereby ignoring the
subscribe command.
Daniel Spinosa
- The client maintains a set of pending subscriptions until either
-
Compile ESM package that can be used directly in the browser as actioncable.esm.js.
DHH
-
Move action_cable.js to actioncable.js to match naming convention used for other Rails frameworks, and use JS console to communicate the deprecation.
DHH
-
Stop transpiling the UMD package generated as actioncable.js and drop the IE11 testing that relied on that.
DHH
-
Truncate broadcast logging messages.
J Smith
-
OpenSSL constants are now used for Digest computations.
Dirkjan Bussink
-
The Action Cable client now includes safeguards to prevent a "thundering
herd" of client reconnects after server connectivity loss:- The client will wait a random amount between 1x and 3x of the stale
threshold after the server's last ping before making the first
reconnection attempt. - Subsequent reconnection attempts now use exponential backoff instead of
logarithmic backoff. To allow the delay between reconnection attempts to
increase slowly at first, the default exponentiation base is < 2. - Random jitter is applied to each delay between reconnection attempts.
Jonathan Hefner
- The client will wait a random amount between 1x and 3x of the stale
Action Mailbox
-
Removed deprecated environment variable
MAILGUN_INGRESS_API_KEY
.Rafael Mendonça França
-
Removed deprecated
Rails.application.credentials.action_mailbox.mailgun_api_key
.Rafael Mendonça França
-
Add
attachments
to the list of permitted parameters for inbound emails conductor.When using the conductor to test inbound emails with attachments, this prevents an
unpermitted parameter warning in default configurations, and prevents errors for
applications that set:config.action_controller.action_on_unpermitted_parameters = :raise
David Jones, Dana Henke
-
Add ability to configure ActiveStorage service
for storing email raw source.# config/storage.yml incoming_emails: service: Disk root: /secure/dir/for/emails/only
config.action_mailbox.storage_service = :incoming_emails
Yurii Rashkovskii
-
Add ability to incinerate an inbound message through the conductor interface.
Santiago Bartesaghi
-
OpenSSL constants are now used for Digest computations.
Dirkjan Bussink
Action Mailer
-
Remove deprecated
ActionMailer::DeliveryJob
andActionMailer::Parameterized::DeliveryJob
in favor ofActionMailer::MailDeliveryJob
.Rafael Mendonça França
-
email_address_with_name
returns just the address if name is blank.Thomas Hutterer
-
Configures a default of 5 for both
open_timeout
andread_timeout
for SMTP Settings.André Luis Leal Cardoso Junior
Action Pack
-
Deprecate
Rails.application.config.action_controller.urlsafe_csrf_tokens
. This config is now always enabled.Étienne Barrié
-
Instance variables set in requests in a
ActionController::TestCase
are now cleared before the next requestThis means if you make multiple requests in the same test, instance variables set in the first request will
not persist into the second one. (It's not recommended to make multiple requests in the same test.)Alex Ghiculescu
-
Rails.application.executor
hooks can now be called around every request in aActionController::TestCase
This helps to better simulate request or job local state being reset between requests and prevent state
leaking from one request to another.To enable this, set
config.active_support.executor_around_test_case = true
(this is the default in Rails 7).Alex Ghiculescu
-
Consider onion services secure for cookies.
Justin Tracey
-
Remove deprecated
Rails.config.action_view.raise_on_missing_translations
.Rafael Mendonça França
-
Remove deprecated support to passing a path to
fixture_file_upload
relative tofixture_path
.Rafael Mendonça França
-
Remove deprecated
ActionDispatch::SystemTestCase#host!
.Rafael Mendonça França
-
Remove deprecated
Rails.config.action_dispatch.hosts_response_app
.Rafael Mendonça França
-
Remove deprecated
ActionDispatch::Response.return_only_media_type_on_content_type
.Rafael Mendonça França
-
Raise
ActionController::Redirecting::UnsafeRedirectError
for unsaferedirect_to
redirects.This allows
rescue_from
to be used to add a default fallback route:rescue_from ActionController::Redirecting::UnsafeRedirectError do redirect_to root_url end
Kasper Timm Hansen, Chris Oliver
-
Add
url_from
to verify a redirect location is internal.Takes the open redirect protection from
redirect_to
so users can wrap a
param, and fall back to an alternate redirect URL when the param provided
one is unsafe.def create redirect_to url_from(params[:redirect_url]) || root_url end
dmcge, Kasper Timm Hansen
-
Allow Capybara driver name overrides in
SystemTestCase::driven_by
Allow users to prevent conflicts among drivers that use the same driver
type (selenium, poltergeist, webkit, rack test).Fixes #42502
Chris LaRose
-
Allow multiline to be passed in routes when using wildcard segments.
Previously routes with newlines weren't detected when using wildcard segments, returning
aNo route matches
error.
After this change, routes with newlines are detected on wildcard segments. Exampledraw do get "/wildcard/*wildcard_segment", to: SimpleApp.new("foo#index"), as: :wildcard end # After the change, the path matches. assert_equal "/wildcard/a%0Anewline", url_helpers.wildcard_path(wildcard_segment: "a\nnewline")
Fixes #39103
Ignacio Chiazzo
-
Treat html suffix in controller translation.
Rui Onodera, Gavin Miller
-
Allow permitting numeric params.
Previously it was impossible to permit different fields on numeric parameters.
After this change you can specify different fields for each numbered parameter.
For example params like,book: { authors_attributes: { '0': { name: "William Shakespeare", age_of_death: "52" }, '1': { name: "Unattributed Assistant" }, '2': "Not a hash", 'new_record': { name: "Some name" } } }
Before you could permit name on each author with,
permit book: { authors_attributes: [ :name ] }
After this change you can permit different keys on each numbered element,
permit book: { authors_attributes: { '1': [ :name ], '0': [ :name, :age_of_death ] } }
Fixes #41625
Adam Hess
-
Update
HostAuthorization
middleware to render debug info only
whenconfig.consider_all_requests_local
is set to true.Also, blocked host info is always logged with level
error
.Fixes #42813
Nikita Vyrko
-
Add Server-Timing middleware
Server-Timing specification defines how the server can communicate to browsers performance metrics
about the request it is responding to.The ServerTiming middleware is enabled by default on
development
environment by default using the
config.server_timing
setting and set the relevant duration metrics in theServer-Timing
headerThe full specification for Server-Timing header can be found in: https://www.w3.org/TR/server-timing/#dfn-server-timing-header-field
Sebastian Sogamoso, Guillermo Iguaran
-
Use a static error message when raising
ActionDispatch::Http::Parameters::ParseError
to avoid inadvertently logging the HTTP request body at thefatal
level when it contains
malformed JSON.Fixes #41145
Aaron Lahey
-
Add
Middleware#delete!
to delete middleware or raise if not found.Middleware#delete!
works just likeMiddleware#delete
but will
raise an error if the middleware isn't found.Alex Ghiculescu, Petrik de Heus, Junichi Sato
-
Raise error on unpermitted open redirects.
Add
allow_other_host
options toredirect_to
.
Opt in to this behaviour withActionController::Base.raise_on_open_redirects = true
.Gannon McGibbon
-
Deprecate
poltergeist
andwebkit
(capybara-webkit) driver registration for system testing (they will be removed in Rails 7.1). Addcuprite
instead.Poltergeist and capybara-webkit are already not maintained. These usage in Rails are removed for avoiding confusing users.
Cuprite is a good alternative to Poltergeist. Some guide descriptions are replaced from Poltergeist to Cuprite.
Yusuke Iwaki
-
Exclude additional flash types from
ActionController::Base.action_methods
.Ensures that additional flash types defined on ActionController::Base subclasses
are not listed as actions on that controller.class MyController < ApplicationController add_flash_types :hype end MyController.action_methods.include?('hype') # => false
Gavin Morrice
-
OpenSSL constants are now used for Digest computations.
Dirkjan Bussink
-
Remove IE6-7-8 file download related hack/fix from ActionController::DataStreaming module.
Due to the age of those versions of IE this fix is no longer relevant, more importantly it creates an edge-case for unexpected Cache-Control headers.
Tadas Sasnauskas
-
Configuration setting to skip logging an uncaught exception backtrace when the exception is
present inrescued_responses
.It may be too noisy to get all backtraces logged for applications that manage uncaught
exceptions viarescued_responses
andexceptions_app
.
config.action_dispatch.log_rescued_responses
(defaults totrue
) can be set tofalse
in
this case, so that only exceptions not found inrescued_responses
will be logged.Alexander Azarov, Mike Dalessio
-
Ignore file fixtures on
db:fixtures:load
.Kevin Sjöberg
-
Fix ActionController::Live controller test deadlocks by removing the body buffer size limit for tests.
Dylan Thacker-Smith
-
New
ActionController::ConditionalGet#no_store
method to set HTTP cache controlno-store
directive.Tadas Sasnauskas
-
Drop support for the
SERVER_ADDR
header.Following up rack/rack#1573 and #42349.
Ricardo Díaz
-
Set session options when initializing a basic session.
Gannon McGibbon
-
Add
cache_control: {}
option tofresh_when
andstale?
.Works as a shortcut to set
response.cache_control
with the above methods.Jacopo Beschi
-
Writing into a disabled session will now raise an error.
Previously when no session store was set, writing into the session would silently fail.
Jean Boussier
-
Add support for 'require-trusted-types-for' and 'trusted-types' headers.
Fixes #42034.
lfalcao
-
Remove inline styles and address basic accessibility issues on rescue templates.
Jacob Herrington
-
Add support for 'private, no-store' Cache-Control headers.
Previously, 'no-store' was exclusive; no other directives could be specified.
Alex Smith
-
Expand payload of
unpermitted_parameters.action_controller
instrumentation to allow subscribers to
know which controller action received unpermitted parameters.bbuchalter
-
Add
ActionController::Live#send_stream
that makes it more convenient to send generated streams:send_stream(filename: "subscribers.csv") do |stream| stream.writeln "email_address,updated_at" @subscribers.find_each do |subscriber| stream.writeln [ subscriber.email_address, subscriber.updated_at ].join(",") end end
DHH
-
Add
ActionController::Live::Buffer#writeln
to write a line to the stream with a newline included.DHH
-
ActionDispatch::Request#content_type
now returned Content-Type header as it is.Previously,
ActionDispatch::Request#content_type
returned value does NOT contain charset part.
This behavior changed to returned Content-Type header containing charset part as it is.If you want just MIME type, please use
ActionDispatch::Request#media_type
instead.Before:
request = ActionDispatch::Request.new("CONTENT_TYPE" => "text/csv; header=present; charset=utf-16", "REQUEST_METHOD" => "GET") request.content_type #=> "text/csv"
After:
request = ActionDispatch::Request.new("Content-Type" => "text/csv; header=present; charset=utf-16", "REQUEST_METHOD" => "GET") request.content_type #=> "text/csv; header=present; charset=utf-16" request.media_type #=> "text/csv"
Rafael Mendonça França
-
Change
ActionDispatch::Request#media_type
to returnnil
when the request don't have aContent-Type
header.Rafael Mendonça França
-
Fix error in
ActionController::LogSubscriber
that would happen when throwing inside a controller action.Janko Marohnić
-
Allow anything with
#to_str
(likeAddressable::URI
) as aredirect_to
location.ojab
-
Change the request method to a
GET
when passing failed requests down toconfig.exceptions_app
.Alex Robbin
-
Deprecate the ability to assign a single value to
config.action_dispatch.trusted_proxies
asRemoteIp
middleware behaves inconsistently depending on whether this is configured
with a single value or an enumerable.Fixes #40772.
Christian Sutter
-
Add
redirect_back_or_to(fallback_location, **)
as a more aesthetically pleasing version ofredirect_back fallback_location:, **
.
The old method name is retained without explicit deprecation.DHH
Action Text
-
Fix an issue with how nested lists were displayed when converting to plain text
Matt Swanson
-
Allow passing in a custom
direct_upload_url
orblob_url_template
torich_text_area_tag
.Lucas Mansur
-
Make the Action Text + Trix JavaScript and CSS available through the asset pipeline.
DHH
-
OpenSSL constants are now used for Digest computations.
Dirkjan Bussink
-
Add support for passing
form:
option torich_text_area_tag
and
rich_text_area
helpers to specify the<input type="hidden" form="...">
value.Sean Doyle
-
Add
config.action_text.attachment_tag_name
, to specify the HTML tag that contains attachments.Mark VanLandingham
-
Expose how we render the HTML surrounding rich text content as an
extensiblelayouts/action_view/contents/_content.html.erb
template to
encourage user-land customizations, while retaining private API control over how
the rich text itself is rendered byaction_text/contents/_content.html.erb
partial.Sean Doyle
-
Add
with_all_rich_text
method to eager load all rich text associations on a model at once.Matt Swanson, DHH
Action View
-
Support
include_hidden:
option in calls to
ActionView::Helper::FormBuilder#file_field
withmultiple: true
to
support submitting an empty collection of files.form.file_field :attachments, multiple: true # => <input type="hidden" autocomplete="off" name="post[attachments][]" value=""> <input type="file" multiple="multiple" id="post_attachments" name="post[attachments][]"> form.file_field :attachments, multiple: true, include_hidden: false # => <input type="file" multiple="multiple" id="post_attachments" name="post[attachments][]">
Sean Doyle
-
Fix
number_with_precision(raise: true)
always raising even on valid numbers.Pedro Moreira
-
Support
fields model: [@nested, @model]
the same way asform_with model: [@nested, @model]
.Sean Doyle
-
Infer HTTP verb
[method]
from a model or Array with model as the first
argument tobutton_to
when combined with a block:button_to(Workshop.find(1)){ "Update" } #=> <form method="post" action="/workshops/1" class="button_to"> #=> <input type="hidden" name="_method" value="patch" autocomplete="off" /> #=> <button type="submit">Update</button> #=> </form> button_to([ Workshop.find(1), Session.find(1) ]) { "Update" } #=> <form method="post" action="/workshops/1/sessions/1" class="button_to"> #=> <input type="hidden" name="_method" value="patch" autocomplete="off" /> #=> <button type="submit">Update</button> #=> </form>
Sean Doyle
-
Support passing a Symbol as the first argument to
FormBuilder#button
:form.button(:draft, value: true) # => <button name="post[draft]" value="true" type="submit">Create post</button> form.button(:draft, value: true) do content_tag(:strong, "Save as draft") end # => <button name="post[draft]" value="true" type="submit"> # <strong>Save as draft</strong> # </button>
Sean Doyle
-
Introduce the
field_name
view helper, along with the
FormBuilder#field_name
counterpart:form_for @post do |f| f.field_tag :tag, name: f.field_name(:tag, multiple: true) # => <input type="text" name="post[tag][]"> end
Sean Doyle
-
Execute the
ActionView::Base.field_error_proc
within the context of the
ActionView::Base
instance:config.action_view.field_error_proc = proc { |html| content_tag(:div, html, class: "field_with_errors") }
Sean Doyle
-
Add support for
button_to ..., authenticity_token: false
button_to "Create", Post.new, authenticity_token: false # => <form class="button_to" method="post" action="/posts"><button type="submit">Create</button></form> button_to "Create", Post.new, authenticity_token: true # => <form class="button_to" method="post" action="/posts"><button type="submit">Create</button><input type="hidden" name="form_token" value="abc123..." autocomplete="off" /></form> button_to "Create", Post.new, authenticity_token: "secret" # => <form class="button_to" method="post" action="/posts"><button type="submit">Create</button><input type="hidden" name="form_token" value="secret" autocomplete="off" /></form>
Sean Doyle
-
Support rendering
<form>
elements without[action]
attributes by:form_with url: false
orform_with ..., html: { action: false }
form_for ..., url: false
orform_for ..., html: { action: false }
form_tag false
orform_tag ..., action: false
button_to "...", false
orbutton_to(false) { ... }
Sean Doyle
-
Add
:day_format
option todate_select
date_select("article", "written_on", day_format: ->(day) { day.ordinalize }) # generates day options like <option value="1">1st</option>\n<option value="2">2nd</option>...
Shunichi Ikegami
-
Allow
link_to
helper to infer link name fromModel#to_s
when it
is used with a single argument:link_to @profile #=> <a href="/profiles/1">Eileen</a>
This assumes the model class implements a
to_s
method like this:class Profile < ApplicationRecord # ... def to_s name end end
Previously you had to supply a second argument even if the
Profile
model implemented a#to_s
method that called thename
method.link_to @profile, @profile.name #=> <a href="/profiles/1">Eileen</a>
Olivier Lacan
-
Support svg unpaired tags for
tag
helper.tag.svg { tag.use('href' => "#cool-icon") } # => <svg><use href="#cool-icon"></svg>
Oleksii Vasyliev
-
Improves the performance of ActionView::Helpers::NumberHelper formatters by avoiding the use of
exceptions as flow control.Mike Dalessio
-
preload_link_tag
properly insertsas
attributes for files withimage
MIME types, such as JPG or SVG.Nate Berkopec
-
Add
weekday_options_for_select
andweekday_select
helper methods. Also addsweekday_select
toFormBuilder
.Drew Bragg, Dana Kashubeck, Kasper Timm Hansen
-
Add
caching?
helper that returns whether the current code path is being cached anduncacheable!
to denote helper methods that can't participate in fragment caching.Ben Toews, John Hawthorn, Kasper Timm Hansen, Joel Hawksley
-
Add
include_seconds
option fortime_field
.<%= form.time_field :foo, include_seconds: false %> # => <input value="16:22" type="time" />
Default includes seconds:
<%= form.time_field :foo %> # => <input value="16:22:01.440" type="time" />
This allows you to take advantage of different rendering options in some browsers.
Alex Ghiculescu
-
Improve error messages when template file does not exist at absolute filepath.
Ted Whang
-
Add
:country_code
option tosms_to
for consistency withphone_to
.Jonathan Hefner
-
OpenSSL constants are now used for Digest computations.
Dirkjan Bussink
-
The
translate
helper now passesdefault
values that aren't
translation keys throughI18n.translate
for interpolation.Jonathan Hefner
-
Adds option
extname
tostylesheet_link_tag
to skip default
.css
extension appended to the stylesheet path.Before:
stylesheet_link_tag "style.less" # <link href="/stylesheets/style.less.scss" rel="stylesheet">
After:
stylesheet_link_tag "style.less", extname: false, skip_pipeline: true, rel: "stylesheet/less" # <link href="/stylesheets/style.less" rel="stylesheet/less">
Abhay Nikam
-
Deprecate
render
locals to be assigned to instance variables.Petrik de Heus
-
Remove legacy default
media=screen
fromstylesheet_link_tag
.André Luis Leal Cardoso Junior
-
Change
ActionView::Helpers::FormBuilder#button
to transformformmethod
attributes into_method="$VERB"
Form Data to enable varied same-form actions:<%= form_with model: post, method: :put do %> <%= form.button "Update" %> <%= form.button "Delete", formmethod: :delete %> <% end %> <%# => <form action="posts/1"> => <input type="hidden" name="_method" value="put"> => <button type="submit">Update</button> => <button type="submit" formmethod="post" name="_method" value="delete">Delete</button> => </form> %>
Sean Doyle
-
Change
ActionView::Helpers::UrlHelper#button_to
to always render a
<button>
element, regardless of whether or not the content is passed as
the first argument or as a block.<%= button_to "Delete", post_path(@post), method: :delete %> # => <form action="/posts/1"><input type="hidden" name="_method" value="delete"><button type="submit">Delete</button></form> <%= button_to post_path(@post), method: :delete do %> Delete <% end %> # => <form action="/posts/1"><input type="hidden" name="_method" value="delete"><button type="submit">Delete</button></form>
Sean Doyle, Dusan Orlovic
-
Add
config.action_view.preload_links_header
to allow disabling of
theLink
header being added by default when usingstylesheet_link_tag
andjavascript_include_tag
.Andrew White
-
The
translate
helper now resolvesdefault
values when anil
key is
specified, instead of always returningnil
.Jonathan Hefner
-
Add
config.action_view.image_loading
to configure the default value of
theimage_tag
:loading
option.By setting
config.action_view.image_loading = "lazy"
, an application can opt in to
lazy loading images sitewide, without changing view code.Jonathan Hefner
-
ActionView::Helpers::FormBuilder#id
returns the value
of the<form>
element'sid
attribute. With amethod
argument, returns
theid
attribute for a form field with that name.<%= form_for @post do |f| %> <%# ... %> <% content_for :sticky_footer do %> <%= form.button(form: f.id) %> <% end %> <% end %>
Sean Doyle
-
ActionView::Helpers::FormBuilder#field_id
returns the value generated by
the FormBuilder for the given attribute name.<%= form_for @post do |f| %> <%= f.label :title %> <%= f.text_field :title, aria: { describedby: f.field_id(:title, :error) } %> <%= tag.span("is blank", id: f.field_id(:title, :error) %> <% end %>
Sean Doyle
-
Add
tag.attributes
to transform a Hash into HTML Attributes, ready to be
interpolated into ERB.<input <%= tag.attributes(type: :text, aria: { label: "Search" }) %> > # => <input type="text" aria-label="Search">
Sean Doyle
Active Job
-
Remove deprecated
:return_false_on_aborted_enqueue
option.Rafael Mendonça França
-
Deprecated
Rails.config.active_job.skip_after_callbacks_if_terminated
.Rafael Mendonça França
-
Removed deprecated behavior that was not halting
after_enqueue
/after_perform
callbacks when a
previous callback was halted withthrow :abort
.Rafael Mendonça França
-
Raise an
SerializationError
inSerializer::ModuleSerializer
if the module name is not present.Veerpal Brar
-
Allow a job to retry indefinitely
The
attempts
parameter of theretry_on
method now accepts the
symbol reference:unlimited
in addition to a specific number of retry
attempts to allow a developer to specify that a job should retry
forever until it succeeds.class MyJob < ActiveJob::Base retry_on(AlwaysRetryException, attempts: :unlimited) # the actual job code end
Daniel Morton
-
Added possibility to check on
:priority
in test helper methods
assert_enqueued_with
andassert_performed_with
.Wojciech Wnętrzak
-
OpenSSL constants are now used for Digest computations.
Dirkjan Bussink
-
Add a Serializer for the Range class.
This should allow things like
MyJob.perform_later(range: 1..100)
. -
Communicate enqueue failures to callers of
perform_later
.perform_later
can now optionally take a block which will execute after
the adapter attempts to enqueue the job. The block will receive the job
instance as an argument even if the enqueue was not successful.
Additionally,ActiveJob
adapters now have the ability to raise an
ActiveJob::EnqueueError
which will be caught and stored in the job
instance so code attempting to enqueue jobs can inspect any raised
EnqueueError
using the block.MyJob.perform_later do |job| unless job.successfully_enqueued? if job.enqueue_error&.message == "Redis was unavailable" # invoke some code that will retry the job after a delay end end end
Daniel Morton
-
Don't log rescuable exceptions defined with
rescue_from
.Hu Hailin
-
Allow
rescue_from
to rescue all exceptions.Adrianna Chang, Étienne Barrié
Active Model
-
Remove support to Marshal load Rails 5.x
ActiveModel::AttributeSet
format.Rafael Mendonça França
-
Remove support to Marshal and YAML load Rails 5.x error format.
Rafael Mendonça França
-
Remove deprecated support to use
[]=
inActiveModel::Errors#messages
.Rafael Mendonça França
-
Remove deprecated support to
delete
errors fromActiveModel::Errors#messages
.Rafael Mendonça França
-
Remove deprecated support to
clear
errors fromActiveModel::Errors#messages
.Rafael Mendonça França
-
Remove deprecated support concat errors to
ActiveModel::Errors#messages
.Rafael Mendonça França
-
Remove deprecated
ActiveModel::Errors#to_xml
.Rafael Mendonça França
-
Remove deprecated
ActiveModel::Errors#keys
.Rafael Mendonça França
-
Remove deprecated
ActiveModel::Errors#values
.Rafael Mendonça França
-
Remove deprecated
ActiveModel::Errors#slice!
.Rafael Mendonça França
-
Remove deprecated
ActiveModel::Errors#to_h
.Rafael Mendonça França
-
Remove deprecated enumeration of
ActiveModel::Errors
instances as a Hash.Rafael Mendonça França
-
Clear secure password cache if password is set to
nil
Before:
user.password = 'something'
user.password = niluser.password # => 'something'
Now:
user.password = 'something'
user.password = niluser.password # => nil
Markus Doits
-
Introduce
ActiveModel::API
.Make
ActiveModel::API
the minimum API to talk with Action Pack and Action View.
This will allow adding more functionality toActiveModel::Model
.Petrik de Heus, Nathaniel Watts
-
Fix dirty check for Float::NaN and BigDecimal::NaN.
Float::NaN and BigDecimal::NaN in Ruby are special values
and can't be compared with==
.Marcelo Lauxen
-
Fix
to_json
forActiveModel::Dirty
object.Exclude
mutations_from_database
attribute from json as it lead to recursion.Anil Maurya
-
Add
ActiveModel::AttributeSet#values_for_database
.Returns attributes with values for assignment to the database.
Chris Salzberg
-
Fix delegation in ActiveModel::Type::Registry#lookup and ActiveModel::Type.lookup.
Passing a last positional argument
{}
would be incorrectly considered as keyword argument.Benoit Daloze
-
Cache and re-use generated attribute methods.
Generated methods with identical implementations will now share their instruction sequences
leading to reduced memory retention, and slightly faster load time.Jean Boussier
-
Add
in: range
parameter tonumericality
validator.Michal Papis
-
Add
locale
argument toActiveModel::Name#initialize
to be used to generate thesingular
,
plural
,route_key
andsingular_route_key
values.Lukas Pokorny
-
Make ActiveModel::Errors#inspect slimmer for readability
lulalala
Active Record
-
Better handle SQL queries with invalid encoding.
Post.create(name: "broken \xC8 UTF-8")
Would cause all adapters to fail in a non controlled way in the code
responsible to detect write queries.The query is now properly passed to the database connection, which might or might
not be able to handle it, but will either succeed or failed in a more correct way.Jean Boussier
-
Move database and shard selection config options to a generator.
Rather than generating the config options in
production.rb
when applications are created, applications can now run a generator to create an initializer and uncomment / update options as needed. All multi-db configuration can be implemented in this initializer.Eileen M. Uchitelle
-
Remove deprecated
ActiveRecord::DatabaseConfigurations::DatabaseConfig#spec_name
.Rafael Mendonça França
-
Remove deprecated
ActiveRecord::Connection#in_clause_length
.Rafael Mendonça França
-
Remove deprecated
ActiveRecord::Connection#allowed_index_name_length
.Rafael Mendonça França
-
Remove deprecated
ActiveRecord::Base#remove_connection
.Rafael Mendonça França
-
Load STI Models in fixtures
Data from Fixtures now loads based on the specific class for models with
Single Table Inheritance. This affects enums defined in subclasses, previously
the value of these fields was not parsed and remainednil
Andres Howard
-
#authenticate
returns false when the password is blank instead of raising an error.Muhammad Muhammad Ibrahim
-
Fix
ActiveRecord::QueryMethods#in_order_of
behavior for integer enums.ActiveRecord::QueryMethods#in_order_of
didn't work as expected for enums stored as integers in the database when passing an array of strings or symbols as the order argument. This unexpected behavior occurred because the string or symbol values were not casted to match the integers in the database.The following example now works as expected:
class Book < ApplicationRecord enum status: [:proposed, :written, :published] end Book.in_order_of(:status, %w[written published proposed])
Alexandre Ruban
-
Ignore persisted in-memory records when merging target lists.
Kevin Sjöberg
-
Add a new option
:update_only
toupsert_all
to configure the list of columns to update in case of conflict.Before, you could only customize the update SQL sentence via
:on_duplicate
. There is now a new option:update_only
that lets you provide a list of columns to update in case of conflict:Commodity.upsert_all( [ { id: 2, name: "Copper", price: 4.84 }, { id: 4, name: "Gold", price: 1380.87 }, { id: 6, name: "Aluminium", price: 0.35 } ], update_only: [:price] # Only prices will be updated )
Jorge Manrubia
-
Remove deprecated
ActiveRecord::Result#map!
andActiveRecord::Result#collect!
.Rafael Mendonça França
-
Remove deprecated
ActiveRecord::Base.configurations.to_h
.Rafael Mendonça França
-
Remove deprecated
ActiveRecord::Base.configurations.default_hash
.Rafael Mendonça França
-
Remove deprecated
ActiveRecord::Base.arel_attribute
.Rafael Mendonça França
-
Remove deprecated
ActiveRecord::Base.connection_config
.Rafael Mendonça França
-
Filter attributes in SQL logs
Previously, SQL queries in logs containing
ActiveRecord::Base.filter_attributes
were not filtered.Now, the filter attributes will be masked
[FILTERED]
in the logs whenprepared_statement
is enabled.# Before: Foo Load (0.2ms) SELECT "foos".* FROM "foos" WHERE "foos"."passw" = ? LIMIT ? [["passw", "hello"], ["LIMIT", 1]] # After: Foo Load (0.5ms) SELECT "foos".* FROM "foos" WHERE "foos"."passw" = ? LIMIT ? [["passw", "[FILTERED]"], ["LIMIT", 1]]
Aishwarya Subramanian
-
Remove deprecated
Tasks::DatabaseTasks.spec
.Rafael Mendonça França
-
Remove deprecated
Tasks::DatabaseTasks.current_config
.Rafael Mendonça França
-
Deprecate
Tasks::DatabaseTasks.schema_file_type
.Rafael Mendonça França
-
Remove deprecated
Tasks::DatabaseTasks.dump_filename
.Rafael Mendonça França
-
Remove deprecated
Tasks::DatabaseTasks.schema_file
.Rafael Mendonça França
-
Remove deprecated
environment
andname
arguments fromTasks::DatabaseTasks.schema_up_to_date?
.Rafael Mendonça França
-
Merging conditions on the same column no longer maintain both conditions,
and will be consistently replaced by the latter condition.# Rails 6.1 (IN clause is replaced by merger side equality condition) Author.where(id: [david.id, mary.id]).merge(Author.where(id: bob)) # => [bob] # Rails 6.1 (both conflict conditions exists, deprecated) Author.where(id: david.id..mary.id).merge(Author.where(id: bob)) # => [] # Rails 6.1 with rewhere to migrate to Rails 7.0's behavior Author.where(id: david.id..mary.id).merge(Author.where(id: bob), rewhere: true) # => [bob] # Rails 7.0 (same behavior with IN clause, mergee side condition is consistently replaced) Author.where(id: [david.id, mary.id]).merge(Author.where(id: bob)) # => [bob] Author.where(id: david.id..mary.id).merge(Author.where(id: bob)) # => [bob] *Rafael Mendonça França*
-
Remove deprecated support to
Model.reorder(nil).first
to search using non-deterministic order.Rafael Mendonça França
-
Remove deprecated rake tasks:
db:schema:load_if_ruby
db:structure:dump
db:structure:load
db:structure:load_if_sql
db:structure:dump:#{name}
db:structure:load:#{name}
db:test:load_structure
db:test:load_structure:#{name}
Rafael Mendonça França
-
Remove deprecated
DatabaseConfig#config
method.Rafael Mendonça França
-
Rollback transactions when the block returns earlier than expected.
Before this change, when a transaction block returned early, the transaction would be committed.
The problem is that timeouts triggered inside the transaction block was also making the incomplete transaction
to be committed, so in order to avoid this mistake, the transaction block is rolled back.Rafael Mendonça França
-
Add middleware for automatic shard swapping.
Provides a basic middleware to perform automatic shard swapping. Applications will provide a resolver which will determine for an individual request which shard should be used. Example:
config.active_record.shard_resolver = ->(request) { subdomain = request.subdomain tenant = Tenant.find_by_subdomain!(subdomain) tenant.shard }
See guides for more details.
Eileen M. Uchitelle, John Crepezzi
-
Remove deprecated support to pass a column to
type_cast
.Rafael Mendonça França
-
Remove deprecated support to type cast to database values
ActiveRecord::Base
objects.Rafael Mendonça França
-
Remove deprecated support to quote
ActiveRecord::Base
objects.Rafael Mendonça França
-
Remove deprecacated support to resolve connection using
"primary"
as connection specification name.Rafael Mendonça França
-
Remove deprecation warning when using
:interval
column is used in PostgreSQL database.Now, interval columns will return
ActiveSupport::Duration
objects instead of strings.To keep the old behavior, you can add this line to your model:
attribute :column, :string
Rafael Mendonça França
-
Remove deprecated support to YAML load
ActiveRecord::Base
instance in the Rails 4.2 and 4.1 formats.Rafael Mendonça França
-
Remove deprecated option
:spec_name
in theconfigs_for
method.Rafael Mendonça França
-
Remove deprecated
ActiveRecord::Base.allow_unsafe_raw_sql
.Rafael Mendonça França
-
Fix regression bug that caused ignoring additional conditions for preloading has_many-through relations.
Fixes #43132
Alexander Pauly
-
Fix
has_many
inversing recursion on models with recursive associations.Gannon McGibbon
-
Add
accepts_nested_attributes_for
support fordelegated_type
class Entry < ApplicationRecord delegated_type :entryable, types: %w[ Message Comment ] accepts_nested_attributes_for :entryable end entry = Entry.create(entryable_type: 'Message', entryable_attributes: { content: 'Hello world' }) # => #<Entry:0x00> # id: 1 # entryable_id: 1, # entryable_type: 'Message' # ...> entry.entryable # => #<Message:0x01> # id: 1 # content: 'Hello world' # ...>
Previously it would raise an error:
Entry.create(entryable_type: 'Message', entryable_attributes: { content: 'Hello world' }) # ArgumentError: Cannot build association `entryable'. Are you trying to build a polymorphic one-to-one association?
Sjors Baltus
-
Use subquery for DELETE with GROUP_BY and HAVING clauses.
Prior to this change, deletes with GROUP_BY and HAVING were returning an error.
After this change, GROUP_BY and HAVING are valid clauses in DELETE queries, generating the following query:
DELETE FROM "posts" WHERE "posts"."id" IN ( SELECT "posts"."id" FROM "posts" INNER JOIN "comments" ON "comments"."post_id" = "posts"."id" GROUP BY "posts"."id" HAVING (count(comments.id) >= 2)) ) [["flagged", "t"]]
Ignacio Chiazzo Cardarello
-
Use subquery for UPDATE with GROUP_BY and HAVING clauses.
Prior to this change, updates with GROUP_BY and HAVING were being ignored, generating a SQL like this:
UPDATE "posts" SET "flagged" = ? WHERE "posts"."id" IN ( SELECT "posts"."id" FROM "posts" INNER JOIN "comments" ON "comments"."post_id" = "posts"."id" ) [["flagged", "t"]]
After this change, GROUP_BY and HAVING clauses are used as a subquery in updates, like this:
UPDATE "posts" SET "flagged" = ? WHERE "posts"."id" IN ( SELECT "posts"."id" FROM "posts" INNER JOIN "comments" ON "comments"."post_id" = "posts"."id" GROUP BY posts.id HAVING (count(comments.id) >= 2) ) [["flagged", "t"]]
Ignacio Chiazzo Cardarello
-
Add support for setting the filename of the schema or structure dump in the database config.
Applications may now set their the filename or path of the schema / structure dump file in their database configuration.
production: primary: database: my_db schema_dump: my_schema_dump_filename.rb animals: database: animals_db schema_dump: false
The filename set in
schema_dump
will be used by the application. If set tofalse
the schema will not be dumped. The database tasks are responsible for adding the database directory to the filename. If a full path is provided, the Rails tasks will use that instead ofActiveRecord::DatabaseTasks.db_dir
.Eileen M. Uchitelle, Ryan Kerr
-
Add
ActiveRecord::Base.prohibit_shard_swapping
to prevent attempts to change the shard within a block.John Crepezzi, Eileen M. Uchitelle
-
Filter unchanged attributes with default function from insert query when
partial_inserts
is disabled.Akshay Birajdar, Jacopo Beschi
-
Add support for FILTER clause (SQL:2003) to Arel.
Currently supported by PostgreSQL 9.4+ and SQLite 3.30+.
Andrey Novikov
-
Automatically set timestamps on record creation during bulk insert/upsert
Prior to this change, only updates during an upsert operation (e.g.
upsert_all
) would touch timestamps (updated_{at,on}
). Now, record creations also touch timestamp columns ({created,updated}_{at,on}
).This behaviour is controlled by the
<model>.record_timestamps
config, matching the behaviour ofcreate
,update
, etc. It can also be overridden by using therecord_timestamps:
keyword argument.Note that this means
upsert_all
on models withrecord_timestamps = false
will no longer touchupdated_{at,on}
automatically.Sam Bostock
-
Don't require
role
when passingshard
toconnected_to
.connected_to
can now be called with ashard
only. Note thatrole
is still inherited ifconnected_to
calls are nested.Eileen M. Uchitelle
-
Add option to lazily load the schema cache on the connection.
Previously, the only way to load the schema cache in Active Record was through the Railtie on boot. This option provides the ability to load the schema cache on the connection after it's been established. Loading the cache lazily on the connection can be beneficial for Rails applications that use multiple databases because it will load the cache at the time the connection is established. Currently Railties doesn't have access to the connections before boot.
To use the cache, set
config.active_record.lazily_load_schema_cache = true
in your application configuration. In addition aschema_cache_path
should be set in your database configuration if you don't want to use the default "db/schema_cache.yml" path.Eileen M. Uchitelle
-
Allow automatic
inverse_of
detection for associations with scopes.Automatic
inverse_of
detection now works for associations with scopes. For
example, thecomments
association here now automatically detects
inverse_of: :post
, so we don't need to pass that option:class Post < ActiveRecord::Base has_many :comments, -> { visible } end class Comment < ActiveRecord::Base belongs_to :post end
Note that the automatic detection still won't work if the inverse
association has a scope. In this example a scope on thepost
association
would still prevent Rails from finding the inverse for thecomments
association.This will be the default for new apps in Rails 7. To opt in:
config.active_record.automatic_scope_inversing = true
Daniel Colson, Chris Bloom
-
Accept optional transaction args to
ActiveRecord::Locking::Pessimistic#with_lock
#with_lock
now accepts transaction options likerequires_new:
,
isolation:
, andjoinable:
John Mileham
-
Adds support for deferrable foreign key constraints in PostgreSQL.
By default, foreign key constraints in PostgreSQL are checked after each statement. This works for most use cases,
but becomes a major limitation when creating related records before the parent record is inserted into the database.
One example of this is looking up / creating a person via one or more unique alias.Person.transaction do alias = Alias .create_with(user_id: SecureRandom.uuid) .create_or_find_by(name: "DHH") person = Person .create_with(name: "David Heinemeier Hansson") .create_or_find_by(id: alias.user_id) end
Using the default behavior, the transaction would fail when executing the first
INSERT
statement.By passing the
:deferrable
option to theadd_foreign_key
statement in migrations, it's possible to defer this
check.add_foreign_key :aliases, :person, deferrable: true
Passing
deferrable: true
doesn't change the default behavior, but allows manually deferring the check using
SET CONSTRAINTS ALL DEFERRED
within a transaction. This will cause the foreign keys to be checked after the
transaction.It's also possible to adjust the default behavior from an immediate check (after the statement), to a deferred check
(after the transaction):add_foreign_key :aliases, :person, deferrable: :deferred
Benedikt Deicke
-
Allow configuring Postgres password through the socket URL.
For example:
ActiveRecord::DatabaseConfigurations::UrlConfig.new( :production, :production, 'postgres:///?user=user&password=secret&dbname=app', {} ).configuration_hash
will now return,
{ :user=>"user", :password=>"secret", :dbname=>"app", :adapter=>"postgresql" }
Abeid Ahmed
-
PostgreSQL: support custom enum types
In migrations, use
create_enum
to add a new enum type, andt.enum
to add a column.def up create_enum :mood, ["happy", "sad"] change_table :cats do |t| t.enum :current_mood, enum_type: "mood", default: "happy", null: false end end
Enums will be presented correctly in
schema.rb
. Note that this is only supported by
the PostgreSQL adapter.Alex Ghiculescu
-
Avoid COMMENT statements in PostgreSQL structure dumps
COMMENT statements are now omitted from the output of
db:structure:dump
when using PostgreSQL >= 11.
This allows loading the dump without a pgsql superuser account.Janosch Müller
-
Add support for generated columns in PostgreSQL adapter
Generated columns are supported since version 12.0 of PostgreSQL. This adds
support of those to the PostgreSQL adapter.create_table :users do |t| t.string :name t.virtual :name_upcased, type: :string, as: 'upper(name)', stored: true end
Michał Begejowicz
-
Remove warning when overwriting existing scopes
Removes the following unnecessary warning message that appeared when overwriting existing scopes
Creating scope :my_scope_name. Overwriting existing method "MyClass.my_scope_name" when overwriting existing scopes
Weston Ganger
-
Use full precision for
updated_at
ininsert_all
/upsert_all
CURRENT_TIMESTAMP
provides differing precision depending on the database,
and not all databases support explicitly specifying additional precision.Instead, we delegate to the new
connection.high_precision_current_timestamp
for the SQL to produce a high precision timestamp on the current database.Fixes #42992
Sam Bostock
-
Add ssl support for postgresql database tasks
Add
PGSSLMODE
,PGSSLCERT
,PGSSLKEY
andPGSSLROOTCERT
to pg_env from database config
when running postgresql database tasks.# config/database.yml production: sslmode: verify-full sslcert: client.crt sslkey: client.key sslrootcert: ca.crt
Environment variables
PGSSLMODE=verify-full PGSSLCERT=client.crt PGSSLKEY=client.key PGSSLROOTCERT=ca.crt
Fixes #42994
Michael Bayucot
-
Avoid scoping update callbacks in
ActiveRecord::Relation#update!
.Making it consistent with how scoping is applied only to the query in
ActiveRecord::Relation#update
and not also to the callbacks from the update itself.Dylan Thacker-Smith
-
Fix 2 cases that inferred polymorphic class from the association's
foreign_type
usingString#constantize
instead of the model'spolymorphic_class_for
.When updating a polymorphic association, the old
foreign_type
was not inferred correctly when:touch
ing the previously associated record- updating the previously associated record's
counter_cache
Jimmy Bourassa
-
Add config option for ignoring tables when dumping the schema cache.
Applications can now be configured to ignore certain tables when dumping the schema cache.
The configuration option can table an array of tables:
config.active_record.schema_cache_ignored_tables = ["ignored_table", "another_ignored_table"]
Or a regex:
config.active_record.schema_cache_ignored_tables = [/^_/]
Eileen M. Uchitelle
-
Make schema cache methods return consistent results.
Previously the schema cache methods
primary_keys
,columns
,columns_hash
, andindexes
would behave differently than one another when a table didn't exist and differently across
database adapters. This change unifies the behavior so each method behaves the same regardless
of adapter.The behavior now is:
columns
: (unchanged) raises a db error if the table does not exist.
columns_hash
: (unchanged) raises a db error if the table does not exist.
primary_keys
: (unchanged) returnsnil
if the table does not exist.
indexes
: (changed for mysql2) returns[]
if the table does not exist.Eileen M. Uchitelle
-
Reestablish connection to previous database after after running
db:schema:load:name
After running
db:schema:load:name
the previous connection is restored.Jacopo Beschi
-
Add database config option
database_tasks
If you would like to connect to an external database without any database
management tasks such as schema management, migrations, seeds, etc. you can set
the per database config optiondatabase_tasks: false
# config/database.yml production: primary: database: my_database adapter: mysql2 animals: database: my_animals_database adapter: mysql2 database_tasks: false
Weston Ganger
-
Fix
ActiveRecord::InternalMetadata
to not be broken byconfig.active_record.record_timestamps = false
Since the model always create the timestamp columns, it has to set them, otherwise it breaks
various DB management tasks.Fixes #42983
-
Add
ActiveRecord::QueryLogs
.Configurable tags can be automatically added to all SQL queries generated by Active Record.
# config/application.rb module MyApp class Application < Rails::Application config.active_record.query_log_tags_enabled = true end end
By default the application, controller and action details are added to the query tags:
class BooksController < ApplicationController def index @books = Book.all end end
GET /books # SELECT * FROM books /*application:MyApp;controller:books;action:index*/
Custom tags containing static values and Procs can be defined in the application configuration:
config.active_record.query_log_tags = [ :application, :controller, :action, { custom_static: "foo", custom_dynamic: -> { Time.now } } ]
Keeran Raj Hawoldar, Eileen M. Uchitelle, Kasper Timm Hansen
-
Added support for multiple databases to
rails db:setup
andrails db:reset
.Ryan Hall
-
Add
ActiveRecord::Relation#structurally_compatible?
.Adds a query method by which a user can tell if the relation that they're
about to use for#or
or#and
is structurally compatible with the
receiver.Kevin Newton
-
Add
ActiveRecord::QueryMethods#in_order_of
.This allows you to specify an explicit order that you'd like records
returned in based on a SQL expression. By default, this will be accomplished
using a case statement, as in:Post.in_order_of(:id, [3, 5, 1])
will generate the SQL:
SELECT "posts".* FROM "posts" ORDER BY CASE "posts"."id" WHEN 3 THEN 1 WHEN 5 THEN 2 WHEN 1 THEN 3 ELSE 4 END ASC
However, because this functionality is built into MySQL in the form of the
FIELD
function, that connection adapter will generate the following SQL
instead:SELECT "posts".* FROM "posts" ORDER BY FIELD("posts"."id", 1, 5, 3) DESC
Kevin Newton
-
Fix
eager_loading?
when ordering withSymbol
.eager_loading?
is triggered correctly when usingorder
with symbols.scope = Post.includes(:comments).order(:"comments.label") => true
Jacopo Beschi
-
Two change tracking methods are added for
belongs_to
associations.The
association_changed?
method (assuming an association named:association
) returns true
if a different associated object has been assigned and the foreign key will be updated in the
next save.The
association_previously_changed?
method returns true if the previous save updated the
association to reference a different associated object.George Claghorn
-
Add option to disable schema dump per-database.
Dumping the schema is on by default for all databases in an application. To turn it off for a
specific database, use theschema_dump
option:# config/database.yml production: schema_dump: false
Luis Vasconcellos, Eileen M. Uchitelle
-
Fix
eager_loading?
when ordering withHash
syntax.eager_loading?
is triggered correctly when usingorder
with hash syntax
on an outer table.Post.includes(:comments).order({ "comments.label": :ASC }).eager_loading? # => true
Jacopo Beschi
-
Move the forcing of clear text encoding to the
ActiveRecord::Encryption::Encryptor
.Fixes #42699.
J Smith
-
partial_inserts
is now disabled by default in new apps.This will be the default for new apps in Rails 7. To opt in:
config.active_record.partial_inserts = true
If a migration removes the default value of a column, this option
would cause old processes to no longer be able to create new records.If you need to remove a column, you should first use
ignored_columns
to stop using it.Jean Boussier
-
Rails can now verify foreign keys after loading fixtures in tests.
This will be the default for new apps in Rails 7. To opt in:
config.active_record.verify_foreign_keys_for_fixtures = true
Tests will not run if there is a foreign key constraint violation in your fixture data.
The feature is supported by SQLite and PostgreSQL, other adapters can also add support for it.
Alex Ghiculescu
-
Clear cached
has_one
association after settingbelongs_to
association tonil
.After setting a
belongs_to
relation tonil
and updating an unrelated attribute on the owner,
the owner should still returnnil
on thehas_one
relation.Fixes #42597.
Michiel de Mare
-
OpenSSL constants are now used for Digest computations.
Dirkjan Bussink
-
Adds support for
if_not_exists
toadd_foreign_key
andif_exists
toremove_foreign_key
.Applications can set their migrations to ignore exceptions raised when adding a foreign key
that already exists or when removing a foreign key that does not exist.Example Usage:
class AddAuthorsForeignKeyToArticles < ActiveRecord::Migration[7.0] def change add_foreign_key :articles, :authors, if_not_exists: true end end
class RemoveAuthorsForeignKeyFromArticles < ActiveRecord::Migration[7.0] def change remove_foreign_key :articles, :authors, if_exists: true end end
Roberto Miranda
-
Prevent polluting ENV during postgresql structure dump/load.
Some configuration parameters were provided to pg_dump / psql via
environment variables which persisted beyond the command being run, and may
have caused subsequent commands and connections to fail. Tasks running
across multiple postgresql databases likerails db:test:prepare
may have
been affected.Samuel Cochran
-
Set precision 6 by default for
datetime
columns.By default, datetime columns will have microseconds precision instead of seconds precision.
Roberto Miranda
-
Allow preloading of associations with instance dependent scopes.
John Hawthorn, John Crepezzi, Adam Hess, Eileen M. Uchitelle, Dinah Shi
-
Do not try to rollback transactions that failed due to a
ActiveRecord::TransactionRollbackError
.Jamie McCarthy
-
Active Record Encryption will now encode values as UTF-8 when using deterministic
encryption. The encoding is part of the encrypted payload, so different encodings for
different values result in different ciphertexts. This can break unique constraints and
queries.The new behavior is configurable via
active_record.encryption.forced_encoding_for_deterministic_encryption
that isEncoding::UTF_8
by default. It can be disabled by setting it tonil
.Jorge Manrubia
-
The MySQL adapter now cast numbers and booleans bind parameters to string for safety reasons.
When comparing a string and a number in a query, MySQL converts the string to a number. So for
instance"foo" = 0
, will implicitly cast"foo"
to0
and will evaluate toTRUE
which can
lead to security vulnerabilities.Active Record already protect against that vulnerability when it knows the type of the column
being compared, however until now it was still vulnerable when using bind parameters:User.where("login_token = ?", 0).first
Would perform:
SELECT * FROM `users` WHERE `login_token` = 0 LIMIT 1;
Now it will perform:
SELECT * FROM `users` WHERE `login_token` = '0' LIMIT 1;
Jean Boussier
-
Fixture configurations (
_fixture
) are now strictly validated.If an error will be raised if that entry contains unknown keys while previously it
would silently have no effects.Jean Boussier
-
Add
ActiveRecord::Base.update!
that works likeActiveRecord::Base.update
but raises exceptions.This allows for the same behavior as the instance method
#update!
at a class level.Person.update!(:all, state: "confirmed")
Dorian Marié
-
Add
ActiveRecord::Base#attributes_for_database
.Returns attributes with values for assignment to the database.
Chris Salzberg
-
Use an empty query to check if the PostgreSQL connection is still active.
An empty query is faster than
SELECT 1
.Heinrich Lee Yu
-
Add
ActiveRecord::Base#previously_persisted?
.Returns
true
if the object has been previously persisted but now it has been deleted. -
Deprecate
partial_writes
in favor ofpartial_inserts
andpartial_updates
.This allows to have a different behavior on update and create.
Jean Boussier
-
Fix compatibility with
psych >= 4
.Starting in Psych 4.0.0
YAML.load
behaves likeYAML.safe_load
. To preserve compatibility,
Active Record's schema cache loader andYAMLColumn
now usesYAML.unsafe_load
if available.Jean Boussier
-
ActiveRecord::Base.logger
is now aclass_attribute
.This means it can no longer be accessed directly through
@@logger
, and that settinglogger =
on a subclass won't change the parent's logger.Jean Boussier
-
Add
.asc.nulls_first
for all databases. Unfortunately MySQL still doesn't likenulls_last
.Keenan Brock
-
Improve performance of
one?
andmany?
by limiting the generated count query to 2 results.Gonzalo Riestra
-
Don't check type when using
if_not_exists
onadd_column
.Previously, if a migration called
add_column
with theif_not_exists
option set to true
thecolumn_exists?
check would look for a column with the same name and type as the migration.Recently it was discovered that the type passed to the migration is not always the same type
as the column after migration. For example a column set to:mediumblob
in the migration will
be casted tobinary
when callingcolumn.type
. Since there is no straightforward way to cast
the type to the database type without running the migration, we opted to drop the type check from
add_column
. This means that migrations adding a duplicate column with a different type will no
longer raise an error.Eileen M. Uchitelle
-
Log a warning message when running SQLite in production.
Using SQLite in production ENV is generally discouraged. SQLite is also the default adapter
in a new Rails application.
For the above reasons log a warning message when running SQLite in production.The warning can be disabled by setting
config.active_record.sqlite3_production_warning=false
.Jacopo Beschi
-
Add option to disable joins for
has_one
associations.In a multiple database application, associations can't join across
databases. When set, this option instructs Rails to generate 2 or
more queries rather than generating joins forhas_one
associations.Set the option on a has one through association:
class Person has_one :dog has_one :veterinarian, through: :dog, disable_joins: true end
Then instead of generating join SQL, two queries are used for
@person.veterinarian
:SELECT "dogs"."id" FROM "dogs" WHERE "dogs"."person_id" = ? [["person_id", 1]] SELECT "veterinarians".* FROM "veterinarians" WHERE "veterinarians"."dog_id" = ? [["dog_id", 1]]
Sarah Vessels, Eileen M. Uchitelle
-
Arel::Visitors::Dot
now renders a complete set of properties when visiting
Arel::Nodes::SelectCore
,SelectStatement
,InsertStatement
,UpdateStatement
, and
DeleteStatement
, which fixes #42026. Previously, some properties were omitted.Mike Dalessio
-
Arel::Visitors::Dot
now supportsArel::Nodes::Bin
,Case
,CurrentRow
,Distinct
,
DistinctOn
,Else
,Except
,InfixOperation
,Intersect
,Lock
,NotRegexp
,Quoted
,
Regexp
,UnaryOperation
,Union
,UnionAll
,When
, andWith
. Previously, these node
types caused an exception to be raised byArel::Visitors::Dot#accept
.Mike Dalessio
-
Optimize
remove_columns
to use a single SQL statement.remove_columns :my_table, :col_one, :col_two
Now results in the following SQL:
ALTER TABLE "my_table" DROP COLUMN "col_one", DROP COLUMN "col_two"
Jon Dufresne
-
Ensure
has_one
autosave association callbacks get called once.Change the
has_one
autosave callback to be non cyclic as well.
By doing this the autosave callback are made more consistent for
all 3 cases:has_many
,has_one
, andbelongs_to
.Petrik de Heus
-
Add option to disable joins for associations.
In a multiple database application, associations can't join across
databases. When set, this option instructs Rails to generate 2 or
more queries rather than generating joins for associations.Set the option on a has many through association:
class Dog has_many :treats, through: :humans, disable_joins: true has_many :humans end
Then instead of generating join SQL, two queries are used for
@dog.treats
:SELECT "humans"."id" FROM "humans" WHERE "humans"."dog_id" = ? [["dog_id", 1]] SELECT "treats".* FROM "treats" WHERE "treats"."human_id" IN (?, ?, ?) [["human_id", 1], ["human_id", 2], ["human_id", 3]]
Eileen M. Uchitelle, Aaron Patterson, Lee Quarella
-
Add setting for enumerating column names in SELECT statements.
Adding a column to a PostgreSQL database, for example, while the application is running can
change the result of wildcardSELECT *
queries, which invalidates the result
of cached prepared statements and raises aPreparedStatementCacheExpired
error.When enabled, Active Record will avoid wildcards and always include column names
inSELECT
queries, which will return consistent results and avoid prepared
statement errors.Before:
Book.limit(5) # SELECT * FROM books LIMIT 5
After:
# config/application.rb module MyApp class Application < Rails::Application config.active_record.enumerate_columns_in_select_statements = true end end # or, configure per-model class Book < ApplicationRecord self.enumerate_columns_in_select_statements = true end
Book.limit(5) # SELECT id, author_id, name, format, status, language, etc FROM books LIMIT 5
Matt Duszynski
-
Allow passing SQL as
on_duplicate
value to#upsert_all
to make it possible to use raw SQL to update columns on conflict:Book.upsert_all( [{ id: 1, status: 1 }, { id: 2, status: 1 }], on_duplicate: Arel.sql("status = GREATEST(books.status, EXCLUDED.status)") )
Vladimir Dementyev
-
Allow passing SQL as
returning
statement to#upsert_all
:Article.insert_all( [ { title: "Article 1", slug: "article-1", published: false }, { title: "Article 2", slug: "article-2", published: false } ], returning: Arel.sql("id, (xmax = '0') as inserted, name as new_name") )
Vladimir Dementyev
-
Deprecate
legacy_connection_handling
.Eileen M. Uchitelle
-
Add attribute encryption support.
Encrypted attributes are declared at the model level. These
are regular Active Record attributes backed by a column with
the same name. The system will transparently encrypt these
attributes before saving them into the database and will
decrypt them when retrieving their values.class Person < ApplicationRecord encrypts :name encrypts :email_address, deterministic: true end
You can learn more in the Active Record Encryption
guide.Jorge Manrubia
-
Changed Arel predications
contains
andoverlaps
to use
quoted_node
so that PostgreSQL arrays are quoted properly.Bradley Priest
-
Add mode argument to record level
strict_loading!
.This argument can be used when enabling strict loading for a single record
to specify that we only want to raise on n plus one queries.developer.strict_loading!(mode: :n_plus_one_only) developer.projects.to_a # Does not raise developer.projects.first.client # Raises StrictLoadingViolationError
Previously, enabling strict loading would cause any lazily loaded
association to raise an error. Usingn_plus_one_only
mode allows us to
lazily load belongs_to, has_many, and other associations that are fetched
through a single query.Dinah Shi
-
Fix Float::INFINITY assignment to datetime column with postgresql adapter.
Before:
# With this config ActiveRecord::Base.time_zone_aware_attributes = true # and the following schema: create_table "postgresql_infinities" do |t| t.datetime "datetime" end # This test fails record = PostgresqlInfinity.create!(datetime: Float::INFINITY) assert_equal Float::INFINITY, record.datetime # record.datetime gets nil
After this commit,
record.datetime
getsFloat::INFINITY
as expected.Shunichi Ikegami
-
Type cast enum values by the original attribute type.
The notable thing about this change is that unknown labels will no longer match 0 on MySQL.
class Book < ActiveRecord::Base enum :status, { proposed: 0, written: 1, published: 2 } end
Before:
# SELECT `books`.* FROM `books` WHERE `books`.`status` = 'prohibited' LIMIT 1 Book.find_by(status: :prohibited) # => #<Book id: 1, status: "proposed", ...> (for mysql2 adapter) # => ActiveRecord::StatementInvalid: PG::InvalidTextRepresentation: ERROR: invalid input syntax for type integer: "prohibited" (for postgresql adapter) # => nil (for sqlite3 adapter)
After:
# SELECT `books`.* FROM `books` WHERE `books`.`status` IS NULL LIMIT 1 Book.find_by(status: :prohibited) # => nil (for all adapters)
Ryuta Kamizono
-
Fixtures for
has_many :through
associations now load timestamps on join tables.Given this fixture:
### monkeys.yml george: name: George the Monkey fruits: apple ### fruits.yml apple: name: apple
If the join table (
fruit_monkeys
) containscreated_at
orupdated_at
columns,
these will now be populated when loading the fixture. Previously, fixture loading
would crash if these columns were required, and leave them as null otherwise.Alex Ghiculescu
-
Allow applications to configure the thread pool for async queries.
Some applications may want one thread pool per database whereas others want to use
a single global thread pool for all queries. By default, Rails will setasync_query_executor
tonil
which will not initialize any executor. Ifload_async
is called and no executor
has been configured, the query will be executed in the foreground.To create one thread pool for all database connections to use applications can set
config.active_record.async_query_executor
to:global_thread_pool
and optionally define
config.active_record.global_executor_concurrency
. This defaults to 4. For applications that want
to have a thread pool for each database connection,config.active_record.async_query_executor
can
be set to:multi_thread_pool
. The configuration for each thread pool is set in the database
configuration.Eileen M. Uchitelle
-
Allow new syntax for
enum
to avoid leading_
from reserved options.Before:
class Book < ActiveRecord::Base enum status: [ :proposed, :written ], _prefix: true, _scopes: false enum cover: [ :hard, :soft ], _suffix: true, _default: :hard end
After:
class Book < ActiveRecord::Base enum :status, [ :proposed, :written ], prefix: true, scopes: false enum :cover, [ :hard, :soft ], suffix: true, default: :hard end
Ryuta Kamizono
-
Add
ActiveRecord::Relation#load_async
.This method schedules the query to be performed asynchronously from a thread pool.
If the result is accessed before a background thread had the opportunity to perform
the query, it will be performed in the foreground.This is useful for queries that can be performed long enough before their result will be
needed, or for controllers which need to perform several independent queries.def index @categories = Category.some_complex_scope.load_async @posts = Post.some_complex_scope.load_async end
Active Record logs will also include timing info for the duration of how long
the main thread had to wait to access the result. This timing is useful to know
whether or not it's worth to load the query asynchronously.DEBUG -- : Category Load (62.1ms) SELECT * FROM `categories` LIMIT 50 DEBUG -- : ASYNC Post Load (64ms) (db time 126.1ms) SELECT * FROM `posts` LIMIT 100
The duration in the first set of parens is how long the main thread was blocked
waiting for the results, and the second set of parens with "db time" is how long
the entire query took to execute.Jean Boussier
-
Implemented
ActiveRecord::Relation#excluding
method.This method excludes the specified record (or collection of records) from
the resulting relation:Post.excluding(post) Post.excluding(post_one, post_two)
Also works on associations:
post.comments.excluding(comment) post.comments.excluding(comment_one, comment_two)
This is short-hand for
Post.where.not(id: post.id)
(for a single record)
andPost.where.not(id: [post_one.id, post_two.id])
(for a collection).Glen Crawford
-
Skip optimised #exist? query when #include? is called on a relation
with a having clause.Relations that have aliased select values AND a having clause that
references an aliased select value would generate an error when
#include? was called, due to an optimisation that would generate
call #exists? on the relation instead, which effectively alters
the select values of the query (and thus removes the aliased select
values), but leaves the having clause intact. Because the having
clause is then referencing an aliased column that is no longer
present in the simplified query, an ActiveRecord::InvalidStatement
error was raised.A sample query affected by this problem:
Author.select('COUNT(*) as total_posts', 'authors.*') .joins(:posts) .group(:id) .having('total_posts > 2') .include?(Author.first)
This change adds an addition check to the condition that skips the
simplified #exists? query, which simply checks for the presence of
a having clause.Fixes #41417.
Michael Smart
-
Increment postgres prepared statement counter before making a prepared statement, so if the statement is aborted
without Rails knowledge (e.g., if app gets killed during long-running query or due to Rack::Timeout), app won't end
up in perpetual crash state for being inconsistent with PostgreSQL.wbharding, Martin Tepper
-
Add ability to apply
scoping
toall_queries
.Some applications may want to use the
scoping
method but previously it only
worked on certain types of queries. This change allows thescoping
method to apply
to all queries for a model in a block.Post.where(blog_id: post.blog_id).scoping(all_queries: true) do post.update(title: "a post title") # adds `posts.blog_id = 1` to the query end
Eileen M. Uchitelle
-
ActiveRecord::Calculations.calculate
called with:average
(aliased asActiveRecord::Calculations.average
) will now use column-based
type casting. This means that floating-point number columns will now be
aggregated asFloat
and decimal columns will be aggregated asBigDecimal
.Integers are handled as a special case returning
BigDecimal
always
(this was the case before already).# With the following schema: create_table "measurements" do |t| t.float "temperature" end # Before: Measurement.average(:temperature).class # => BigDecimal # After: Measurement.average(:temperature).class # => Float
Before this change, Rails just called
to_d
on average aggregates from the
database adapter. This is not the case anymore. If you relied on that kind
of magic, you now need to register your ownActiveRecord::Type
(seeActiveRecord::Attributes::ClassMethods
for documentation).Josua Schmid
-
PostgreSQL: introduce
ActiveRecord::ConnectionAdapters::PostgreSQLAdapter.datetime_type
.This setting controls what native type Active Record should use when you call
datetime
in
a migration or schema. It takes a symbol which must correspond to one of the configured
NATIVE_DATABASE_TYPES
. The default is:timestamp
, meaningt.datetime
in a migration
will create a "timestamp without time zone" column. To use "timestamp with time zone",
change this to:timestamptz
in an initializer.You should run
bin/rails db:migrate
to rebuild your schema.rb if you change this.Alex Ghiculescu
-
PostgreSQL: handle
timestamp with time zone
columns correctly inschema.rb
.Previously they dumped as
t.datetime :column_name
, now they dump ast.timestamptz :column_name
,
and are created astimestamptz
columns when the schema is loaded.Alex Ghiculescu
-
Removing trailing whitespace when matching columns in
ActiveRecord::Sanitization.disallow_raw_sql!
.Gannon McGibbon, Adrian Hirt
-
Expose a way for applications to set a
primary_abstract_class
.Multiple database applications that use a primary abstract class that is not
namedApplicationRecord
can now set a specific class to be theprimary_abstract_class
.class PrimaryApplicationRecord self.primary_abstract_class end
When an application boots it automatically connects to the primary or first database in the
database configuration file. In a multiple database application that then callconnects_to
needs to know that the default connection is the same as theApplicationRecord
connection.
However, some applications have a differently namedApplicationRecord
. This prevents Active
Record from opening duplicate connections to the same database.Eileen M. Uchitelle, John Crepezzi
-
Support hash config for
structure_dump_flags
andstructure_load_flags
flags.
Now that Active Record supports multiple databases configuration,
we need a way to pass specific flags for dump/load databases since
the options are not the same for different adapters.
We can use in the original way:ActiveRecord::Tasks::DatabaseTasks.structure_dump_flags = ['--no-defaults', '--skip-add-drop-table'] # or ActiveRecord::Tasks::DatabaseTasks.structure_dump_flags = '--no-defaults --skip-add-drop-table'
And also use it passing a hash, with one or more keys, where the key
is the adapterActiveRecord::Tasks::DatabaseTasks.structure_dump_flags = { mysql2: ['--no-defaults', '--skip-add-drop-table'], postgres: '--no-tablespaces' }
Gustavo Gonzalez
-
Connection specification now passes the "url" key as a configuration for the
adapter if the "url" protocol is "jdbc", "http", or "https". Previously only
urls with the "jdbc" prefix were passed to the Active Record Adapter, others
are assumed to be adapter specification urls.Fixes #41137.
Jonathan Bracy
-
Allow to opt-out of
strict_loading
mode on a per-record base.This is useful when strict loading is enabled application wide or on a
model level.class User < ApplicationRecord has_many :bookmarks has_many :articles, strict_loading: true end user = User.first user.articles # => ActiveRecord::StrictLoadingViolationError user.bookmarks # => #<ActiveRecord::Associations::CollectionProxy> user.strict_loading!(true) # => true user.bookmarks # => ActiveRecord::StrictLoadingViolationError user.strict_loading!(false) # => false user.bookmarks # => #<ActiveRecord::Associations::CollectionProxy> user.articles.strict_loading!(false) # => #<ActiveRecord::Associations::CollectionProxy>
Ayrton De Craene
-
Add
FinderMethods#sole
and#find_sole_by
to find and assert the
presence of exactly one record.Used when you need a single row, but also want to assert that there aren't
multiple rows matching the condition; especially for when database
constraints aren't enough or are impractical.Product.where(["price = %?", price]).sole # => ActiveRecord::RecordNotFound (if no Product with given price) # => #<Product ...> (if one Product with given price) # => ActiveRecord::SoleRecordExceeded (if more than one Product with given price) user.api_keys.find_sole_by(key: key) # as above
Asherah Connor
-
Makes
ActiveRecord::AttributeMethods::Query
respect the getter overrides defined in the model.Before:
class User def admin false # Overriding the getter to always return false end end user = User.first user.update(admin: true) user.admin # false (as expected, due to the getter overwrite) user.admin? # true (not expected, returned the DB column value)
After this commit,
user.admin?
above returns false, as expected.Fixes #40771.
Felipe
-
Allow delegated_type to be specified primary_key and foreign_key.
Since delegated_type assumes that the foreign_key ends with
_id
,
singular_id
defined by it does not work when the foreign_key does
not end withid
. This change fixes it by taking into account
primary_key
andforeign_key
in the options.Ryota Egusa
-
Expose an
invert_where
method that will invert all scope conditions.class User scope :active, -> { where(accepted: true, locked: false) } end User.active # ... WHERE `accepted` = 1 AND `locked` = 0 User.active.invert_where # ... WHERE NOT (`accepted` = 1 AND `locked` = 0)
Kevin Deisz
-
Restore possibility of passing
false
to :polymorphic option ofbelongs_to
.Previously, passing
false
would trigger the option validation logic
to throw an error saying :polymorphic would not be a valid option.glaszig
-
Remove deprecated
database
kwarg fromconnected_to
.Eileen M. Uchitelle, John Crepezzi
-
Allow adding nonnamed expression indexes to be revertible.
Previously, the following code would raise an error, when executed while rolling back,
and the index name should be specified explicitly. Now, the index name is inferred
automatically.add_index(:items, "to_tsvector('english', description)")
Fixes #40732.
fatkodima
-
Only warn about negative enums if a positive form that would cause conflicts exists.
Fixes #39065.
Alex Ghiculescu
-
Add option to run
default_scope
on all queries.Previously, a
default_scope
would only run on select or insert queries. In some cases, like non-Rails tenant sharding solutions, it may be desirable to rundefault_scope
on all queries in order to ensure queries are including a foreign key for the shard (i.e.blog_id
).Now applications can add an option to run on all queries including select, insert, delete, and update by adding an
all_queries
option to the default scope definition.class Article < ApplicationRecord default_scope -> { where(blog_id: Current.blog.id) }, all_queries: true end
Eileen M. Uchitelle
-
Add
where.associated
to check for the presence of an association.# Before: account.users.joins(:contact).where.not(contact_id: nil) # After: account.users.where.associated(:contact)
Also mirrors
where.missing
.Kasper Timm Hansen
-
Allow constructors (
build_association
andcreate_association
) on
has_one :through
associations.Santiago Perez Perret
Active Storage
-
Support transforming empty-ish
has_many_attached
value into[]
(e.g.[""]
).@user.highlights = [""] @user.highlights # => []
Sean Doyle
-
Add ActiveStorage::Blob.compose
to concatenate multiple blobs.Gannon McGibbon
-
Setting custom metadata on blobs are now persisted to remote storage.
joshuamsager
-
Support direct uploads to multiple services.
Dmitry Tsepelev
-
Invalid default content types are deprecated
Blobs created with content_type
image/jpg
,image/pjpeg
,image/bmp
,text/javascript
will now produce
a deprecation warning, since these are not valid content types.These content types will be removed from the defaults in Rails 7.1.
You can set
config.active_storage.silence_invalid_content_types_warning = true
to dismiss the warning.Alex Ghiculescu
-
Emit Active Support instrumentation events from Active Storage analyzers.
Fixes #42930
Shouichi Kamiya
-
Add support for byte range requests
Tom Prats
-
Attachments can be deleted after their association is no longer defined.
Fixes #42514
Don Sisco
-
Make
vips
the default variant processor for new apps.See the upgrade guide for instructions on converting from
mini_magick
tovips
.mini_magick
is
not deprecated, existing apps can keep using it.Breno Gazzola
-
Deprecate
ActiveStorage::Current.host
in favor ofActiveStorage::Current.url_options
which accepts
a host, protocol and port.Santiago Bartesaghi
-
Allow using IAM when signing URLs with GCS.
gcs: service: GCS ... iam: true
RRethy
-
OpenSSL constants are now used for Digest computations.
Dirkjan Bussink
-
Deprecate
config.active_storage.replace_on_assign_to_many
. Future versions of Rails
will behave the same way as when the config is set totrue
.Santiago Bartesaghi
-
Remove deprecated methods:
build_after_upload
,create_after_upload!
in favor ofcreate_and_upload!
,
andservice_url
in favor ofurl
.Santiago Bartesaghi
-
Add support of
strict_loading_by_default
toActiveStorage::Representations
controllers.Anton Topchii, Andrew White
-
Allow to detach an attachment when record is not persisted.
Jacopo Beschi
-
Use libvips instead of ImageMagick to analyze images when
active_storage.variant_processor = vips
.Breno Gazzola
-
Add metadata value for presence of video channel in video blobs.
The
metadata
attribute of video blobs has a new boolean key namedvideo
that is set to
true
if the file has an video channel andfalse
if it doesn't.Breno Gazzola
-
Deprecate usage of
purge
andpurge_later
from the association extension.Jacopo Beschi
-
Passing extra parameters in
ActiveStorage::Blob#url
to S3 Client.This allows calls of
ActiveStorage::Blob#url
to have more interaction with
the S3 Presigner, enabling, amongst other options, custom S3 domain URL
Generation.blob = ActiveStorage::Blob.last blob.url # => https://<bucket-name>.s3.<region>.amazonaws.com/<key> blob.url(virtual_host: true) # => # => https://<bucket-name>/<key>
josegomezr
-
Allow setting a
Cache-Control
on files uploaded to GCS.gcs: service: GCS ... cache_control: "public, max-age=3600"
maleblond
-
The parameters sent to
ffmpeg
for generating a video preview image are now
configurable underconfig.active_storage.video_preview_arguments
.Brendon Muir
-
The ActiveStorage video previewer will now use scene change detection to generate
better preview images (rather than the previous default of using the first frame
of the video). This change requires FFmpeg v3.4+.Jonathan Hefner
-
Add support for ActiveStorage expiring URLs.
rails_blob_path(user.avatar, disposition: "attachment", expires_in: 30.minutes) <%= image_tag rails_blob_path(user.avatar.variant(resize: "100x100"), expires_in: 30.minutes) %>
If you want to set default expiration time for ActiveStorage URLs throughout your application, set
config.active_storage.urls_expire_in
.aki77
-
Allow to purge an attachment when record is not persisted for
has_many_attached
.Jacopo Beschi
-
Add
with_all_variant_records
method to eager load all variant records on an attachment at once.
with_attached_image
scope now eager loads variant records if using variant tracking.Alex Ghiculescu
-
Add metadata value for presence of audio channel in video blobs.
The
metadata
attribute of video blobs has a new boolean key namedaudio
that is set to
true
if the file has an audio channel andfalse
if it doesn't.Breno Gazzola
-
Adds analyzer for audio files.
Breno Gazzola
-
Respect Active Record's primary_key_type in Active Storage migrations.
fatkodima
-
Allow
expires_in
for ActiveStorage signed ids.aki77
-
Allow to purge an attachment when record is not persisted for
has_one_attached
.Jacopo Beschi
-
Add a load hook called
active_storage_variant_record
(providingActiveStorage::VariantRecord
)
to allow for overriding aspects of theActiveStorage::VariantRecord
class. This makes
ActiveStorage::VariantRecord
consistent withActiveStorage::Blob
andActiveStorage::Attachment
that already have load hooks.Brendon Muir
-
ActiveStorage::PreviewError
is raised when a previewer is unable to generate a preview image.Alex Robbin
-
Add
ActiveStorage::Streaming
module that can be included in a controller to get access to#send_blob_stream
,
which wraps the newActionController::Base#send_stream
method to stream a blob from cloud storage:class MyPublicBlobsController < ApplicationController include ActiveStorage::SetBlob, ActiveStorage::Streaming def show http_cache_forever(public: true) do send_blob_stream @blob, disposition: params[:disposition] end end end
DHH
-
Add ability to use pre-defined variants.
class User < ActiveRecord::Base has_one_attached :avatar do |attachable| attachable.variant :thumb, resize: "100x100" attachable.variant :medium, resize: "300x300", monochrome: true end end class Gallery < ActiveRecord::Base has_many_attached :photos do |attachable| attachable.variant :thumb, resize: "100x100" attachable.variant :medium, resize: "300x300", monochrome: true end end <%= image_tag user.avatar.variant(:thumb) %>
fatkodima
-
After setting
config.active_storage.resolve_model_to_route = :rails_storage_proxy
rails_blob_path
andrails_representation_path
will generate proxy URLs by default.Ali Ismayilov
-
Declare
ActiveStorage::FixtureSet
andActiveStorage::FixtureSet.blob
to
improve fixture integration.Sean Doyle
Active Support
-
Fix
ActiveSupport::Duration.build
to support negative values.The algorithm to collect the
parts
of theActiveSupport::Duration
ignored the sign of thevalue
and accumulated incorrect part values. This
impactedActiveSupport::Duration#sum
(which is dependent onparts
) but
notActiveSupport::Duration#eql?
(which is dependent onvalue
).Caleb Buxton, Braden Staudacher
-
Deprecate passing a format to
#to_s
in favor of#to_formatted_s
inArray
,Range
,Date
,DateTime
,Time
,
BigDecimal
,Float
and,Integer
.Rafael Mendonça França
-
Document
ActiveSupport::Testing::Deprecation
.Sam Bostock & Sam Jordan
-
Add
Pathname#existence
.Pathname.new("file").existence&.read
Timo Schilling
-
Remove deprecate
ActiveSupport::Multibyte::Unicode.default_normalization_form
.Rafael Mendonça França
-
Remove deprecated support to use
Range#include?
to check the inclusion of a value in
a date time range is deprecated.Rafael Mendonça França
-
Remove deprecated
URI.parser
.Rafael Mendonça França
-
Remove deprecated
config.active_support.use_sha1_digests
.Rafael Mendonça França
-
Invoking
Object#with_options
without a&block
argument returns the
ActiveSupport::OptionMerger
instance.Sean Doyle
-
Rails.application.executor
hooks can now be called around every testThis helps to better simulate request or job local state being reset around tests and prevents state
leaking from one test to another.However it requires the executor hooks executed in the test environment to be re-entrant.
To enable this, set
config.active_support.executor_around_test_case = true
(this is the default in Rails 7).Jean Boussier
-
ActiveSupport::DescendantsTracker
now mostly delegate toClass#descendants
on Ruby 3.1Ruby now provides a fast
Class#descendants
makingActiveSupport::DescendantsTracker
mostly useless.As a result the following methods are deprecated:
ActiveSupport::DescendantsTracker.direct_descendants
ActiveSupport::DescendantsTracker#direct_descendants
Jean Boussier
-
Fix the
Digest::UUID.uuid_from_hash
behavior for namespace IDs that are different from the ones defined onDigest::UUID
.The new behavior will be enabled by setting the
config.active_support.use_rfc4122_namespaced_uuids
option totrue
and is the default for new apps.The old behavior is the default for upgraded apps and will output a
deprecation warning every time a value that is different than one of
the constants defined on theDigest::UUID
extension is used as the
namespace ID.Alex Robbin, Erich Soares Machado, Eugene Kenny
-
ActiveSupport::Inflector::Inflections#clear(:acronyms)
is now supported,
andinflector.clear
/inflector.clear(:all)
also clears acronyms.Alex Ghiculescu, Oliver Peate
-
ActiveSupport::Dependencies
no longer installs aconst_missing
hook. Before this, you could push to the autoload paths and have constants autoloaded. This feature, known as theclassic
autoloader, has been removed.Xavier Noria
-
Private internal classes of
ActiveSupport::Dependencies
have been deleted, likeActiveSupport::Dependencies::Reference
,ActiveSupport::Dependencies::Blamable
, and others.Xavier Noria
-
The private API of
ActiveSupport::Dependencies
has been deleted. That includes methods likehook!
,unhook!
,depend_on
,require_or_load
,mechanism
, and many others.Xavier Noria
-
Improves the performance of
ActiveSupport::NumberHelper
formatters by avoiding the use of exceptions as flow control.Mike Dalessio
-
Removed rescue block from
ActiveSupport::Cache::RedisCacheStore#handle_exception
Previously, if you provided a
error_handler
toredis_cache_store
, any errors thrown by
the error handler would be rescued and logged only. Removed therescue
clause fromhandle_exception
to allow these to be thrown.Nicholas A. Stuart
-
Allow entirely opting out of deprecation warnings.
Previously if you did
app.config.active_support.deprecation = :silence
, some work would
still be done on each call toActiveSupport::Deprecation.warn
. In very hot paths, this could
cause performance issues.Now, you can make
ActiveSupport::Deprecation.warn
a no-op:config.active_support.report_deprecations = false
This is the default in production for new apps. It is the equivalent to:
config.active_support.deprecation = :silence config.active_support.disallowed_deprecation = :silence
but will take a more optimised code path.
Alex Ghiculescu
-
Faster tests by parallelizing only when overhead is justified by the number
of them.Running tests in parallel adds overhead in terms of database
setup and fixture loading. Now, Rails will only parallelize test executions when
there are enough tests to make it worth it.This threshold is 50 by default, and is configurable via config setting in
your test.rb:config.active_support.test_parallelization_threshold = 100
It's also configurable at the test case level:
class ActiveSupport::TestCase parallelize threshold: 100 end
Jorge Manrubia
-
OpenSSL constants are now used for Digest computations.
Dirkjan Bussink
-
TimeZone.iso8601
now accepts valid ordinal values similar to Ruby'sDate._iso8601
method.
A valid ordinal value will be converted to an instance ofTimeWithZone
using the:year
and:yday
fragments returned fromDate._iso8601
.twz = ActiveSupport::TimeZone["Eastern Time (US & Canada)"].iso8601("21087") twz.to_a[0, 6] == [0, 0, 0, 28, 03, 2021]
Steve Laing
-
Time#change
and methods that call it (e.g.Time#advance
) will now
return aTime
with the timezone argument provided, if the caller was
initialized with a timezone argument.Fixes #42467.
Alex Ghiculescu
-
Allow serializing any module or class to JSON by name.
Tyler Rick, Zachary Scott
-
Raise
ActiveSupport::EncryptedFile::MissingKeyError
when the
RAILS_MASTER_KEY
environment variable is blank (e.g.""
).Sunny Ripert
-
The
from:
option is added toActiveSupport::TestCase#assert_no_changes
.It permits asserting on the initial value that is expected not to change.
assert_no_changes -> { Status.all_good? }, from: true do post :create, params: { status: { ok: true } } end
George Claghorn
-
Deprecate
ActiveSupport::SafeBuffer
's incorrect implicit conversion of objects into string.Except for a few methods like
String#%
, objects must implement#to_str
to be implicitly converted to a String in string operations. In some
circumstancesActiveSupport::SafeBuffer
was incorrectly calling the
explicit conversion method (#to_s
) on them. This behavior is now
deprecated.Jean Boussier
-
Allow nested access to keys on
Rails.application.credentials
.Previously only top level keys in
credentials.yml.enc
could be accessed with method calls. Now any key can.For example, given these secrets:
aws: access_key_id: 123 secret_access_key: 345
Rails.application.credentials.aws.access_key_id
will now return the same thing as
Rails.application.credentials.aws[:access_key_id]
.Alex Ghiculescu
-
Added a faster and more compact
ActiveSupport::Cache
serialization format.It can be enabled with
config.active_support.cache_format_version = 7.0
or
config.load_defaults 7.0
. Regardless of the configuration Active Support
7.0 can read cache entries serialized by Active Support 6.1 which allows to
upgrade without invalidating the cache. However Rails 6.1 can't read the
new format, so all readers must be upgraded before the new format is enabled.Jean Boussier
-
Add
Enumerable#sole
, perActiveRecord::FinderMethods#sole
. Returns the
sole item of the enumerable, raising if no items are found, or if more than
one is.Asherah Connor
-
Freeze
ActiveSupport::Duration#parts
and remove writer methods.Durations are meant to be value objects and should not be mutated.
Andrew White
-
Fix
ActiveSupport::TimeZone#utc_to_local
with fractional seconds.When
utc_to_local_returns_utc_offset_times
is false and the time
instance had fractional seconds the new UTC time instance was out by
a factor of 1,000,000 as theTime.utc
constructor takes a usec
value and not a fractional second value.Andrew White
-
Add
expires_at
argument toActiveSupport::Cache
write
andfetch
to set a cache entry TTL as an absolute time.Rails.cache.write(key, value, expires_at: Time.now.at_end_of_hour)
Jean Boussier
-
Deprecate
ActiveSupport::TimeWithZone.name
so that from Rails 7.1 it will use the default implementation.Andrew White
-
Deprecates Rails custom
Enumerable#sum
andArray#sum
in favor of Ruby's native implementation which
is considerably faster.Ruby requires an initializer for non-numeric type as per examples below:
%w[foo bar].sum('') # instead of %w[foo bar].sum [[1, 2], [3, 4, 5]].sum([]) # instead of [[1, 2], [3, 4, 5]].sum
Alberto Mota
-
Tests parallelization is now disabled when running individual files to prevent the setup overhead.
It can still be enforced if the environment variable
PARALLEL_WORKERS
is present and set to a value greater than 1.Ricardo Díaz
-
Fix proxying keyword arguments in
ActiveSupport::CurrentAttributes
.Marcin Kołodziej
-
Add
Enumerable#maximum
andEnumerable#minimum
to easily calculate the maximum or minimum from extracted
elements of an enumerable.payments = [Payment.new(5), Payment.new(15), Payment.new(10)] payments.minimum(:price) # => 5 payments.maximum(:price) # => 15
This also allows passing enumerables to
fresh_when
andstale?
in Action Controller.
See PR #41404 for an example.Ayrton De Craene
-
ActiveSupport::Cache::MemCacheStore
now accepts an explicitnil
for itsaddresses
argument.config.cache_store = :mem_cache_store, nil # is now equivalent to config.cache_store = :mem_cache_store # and is also equivalent to config.cache_store = :mem_cache_store, ENV["MEMCACHE_SERVERS"] || "localhost:11211" # which is the fallback behavior of Dalli
This helps those migrating from
:dalli_store
, where an explicitnil
was permitted.Michael Overmeyer
-
Add
Enumerable#in_order_of
to put an Enumerable in a certain order by a key.DHH
-
ActiveSupport::Inflector.camelize
behaves expected when provided a symbol:upper
or:lower
argument. Matches
String#camelize
behavior.Alex Ghiculescu
-
Raises an
ArgumentError
when the first argument ofActiveSupport::Notification.subscribe
is
invalid.Vipul A M
-
HashWithIndifferentAccess#deep_transform_keys
now returns aHashWithIndifferentAccess
instead of aHash
.Nathaniel Woodthorpe
-
Consume dalli’s
cache_nils
configuration asActiveSupport::Cache
'sskip_nil
when usingMemCacheStore
.Ritikesh G
-
Add
RedisCacheStore#stats
method similar toMemCacheStore#stats
. Callsredis#info
internally.Ritikesh G
Guides
-
The autoloading guide for
zeitwerk
mode has been revised.Xavier Noria
-
The autoloading guide for
classic
mode has been deleted.Xavier Noria
Railtie
-
Allow localhost with a port by default in development
[Fixes: #43864]
-
Remove deprecated
config
indbconsole
.Rafael Mendonça França
-
Change default
X-XSS-Protection
header to disable XSS auditorThis header has been deprecated and the XSS auditor it triggered
has been removed from all major modern browsers (in favour of
Content Security Policy) that implemented this header to begin with
(Firefox never did).OWASP
suggests setting this header to '0' to disable the default behaviour
on old browsers as it can introduce additional security issues.Added the new behaviour as a framework default from Rails 7.0.
Christian Sutter
-
Scaffolds now use date_field, time_field and datetime_field instead of
date_select, time_select and datetime_select; thus providing native date/time pickers.Martijn Lafeber
-
Fix a regression in which autoload paths were initialized too late.
Xavier Noria
-
Fix activestorage dependency in the npm package.
Rafael Mendonça França
-
New and upgraded Rails apps no longer generate
config/initializers/application_controller_renderer.rb
orconfig/initializers/cookies_serializer.rb
The default value for
cookies_serializer
(:json
) has been moved toconfig.load_defaults("7.0")
.
The new framework defaults file can be used to upgrade the serializer.Alex Ghiculescu
-
New applications get a dependency on the new
debug
gem, replacingbyebug
.Xavier Noria
-
Add SSL support for postgresql in
bin/rails dbconsole
.Fixes #43114.
Michael Bayucot
-
Add support for comments above gem declaration in Rails application templates, e.g.
gem("nokogiri", comment: "For XML")
.Linas Juškevičius
-
The setter
config.autoloader=
has been deleted.zeitwerk
is the only
available autoloading mode.Xavier Noria
-
config.autoload_once_paths
can be configured in the body of the
application class defined inconfig/application.rb
or in the configuration
for environments inconfig/environments/*
.Similarly, engines can configure that collection in the class body of the
engine class or in the configuration for environments.After that, the collection is frozen, and you can autoload from those paths.
They are managed by theRails.autoloaders.once
autoloader, which does not
reload, only autoloads/eager loads.Xavier Noria
-
During initialization, you cannot autoload reloadable classes or modules
like application models, unless they are wrapped in ato_prepare
block.
For example, fromconfig/initializers/*
, or in application, engines, or
railties initializers.Please check the autoloading
guide
for details.Xavier Noria
-
While they are allowed to have elements in common, it is no longer required
thatconfig.autoload_once_paths
is a subset ofconfig.autoload_paths
.
The former are managed by theonce
autoloader. Themain
autoloader
manages the latter minus the former.Xavier Noria
-
Show Rake task description if command is run with
-h
.Adding
-h
(or--help
) to a Rails command that's a Rake task now outputs
the task description instead of the general Rake help.Petrik de Heus
-
Add missing
plugin new
command to help.*Petrik de Heus
-
Fix
config_for
error when there's only a shared root array.Loïc Delmaire
-
Raise an error in generators if an index type is invalid.
Petrik de Heus
-
package.json
now uses a strict version constraint for Rails JavaScript packages on new Rails apps.Zachary Scott, Alex Ghiculescu
-
Modified scaffold generator template so that running
rails g scaffold Author
no longer generates tests called "creating
a Author", "updating a Author", and "destroying a Author".Fixes #40744.
Michael Duchemin
-
Raise an error in generators if a field type is invalid.
Petrik de Heus
-
bin/rails tmp:clear
deletes also files and directories intmp/storage
.George Claghorn
-
Fix compatibility with
psych >= 4
.Starting in Psych 4.0.0
YAML.load
behaves likeYAML.safe_load
. To preserve compatibility
Rails.application.config_for
now usesYAML.unsafe_load
if available.Jean Boussier
-
Allow loading nested locales in engines.
Gannon McGibbon
-
Ensure
Rails.application.config_for
always cast hashes toActiveSupport::OrderedOptions
.Jean Boussier
-
Remove
Rack::Runtime
from the default middleware stack and deprecate
referencing it in middleware operations without adding it back.Hartley McGuire
-
Allow adding additional authorized hosts in development via
ENV['RAILS_DEVELOPMENT_HOSTS']
.Josh Abernathy, Debbie Milburn
-
Add app concern and test keepfiles to generated engine plugins.
Gannon McGibbon
-
Stop generating a license for in-app plugins.
Gannon McGibbon
-
rails app:update
no longer prompts you to overwrite files that are generally modified in the
course of developing a Rails app. See #41083 for
the full list of changes.Alex Ghiculescu
-
Change default branch for new Rails projects and plugins to
main
.Prateek Choudhary
-
The new method
Rails.benchmark
gives you a quick way to measure and log the execution time taken by a block:def test_expensive_stuff Rails.benchmark("test_expensive_stuff") { ... } end
This functionality was available in some contexts only before.
Simon Perepelitsa
-
Applications generated with
--skip-sprockets
no longer getapp/assets/config/manifest.js
andapp/assets/stylesheets/application.css
.Cindy Gao
-
Add support for stylesheets and ERB views to
rails stats
.Joel Hawksley
-
Allow appended root routes to take precedence over internal welcome controller.
Gannon McGibbon