rails 7.0.0
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
-
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
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
attachmentsto 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 = :raiseDavid 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/onlyconfig.action_mailbox.storage_service = :incoming_emailsYurii 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::DeliveryJobandActionMailer::Parameterized::DeliveryJobin favor ofActionMailer::MailDeliveryJob.Rafael Mendonça França
-
email_address_with_namereturns just the address if name is blank.Thomas Hutterer
-
Configures a default of 5 for both
open_timeoutandread_timeoutfor 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::TestCaseare 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.executorhooks can now be called around every request in aActionController::TestCaseThis 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_uploadrelative 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::UnsafeRedirectErrorfor unsaferedirect_toredirects.This allows
rescue_fromto be used to add a default fallback route:rescue_from ActionController::Redirecting::UnsafeRedirectError do redirect_to root_url endKasper Timm Hansen, Chris Oliver
-
Add
url_fromto verify a redirect location is internal.Takes the open redirect protection from
redirect_toso 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 enddmcge, Kasper Timm Hansen
-
Allow Capybara driver name overrides in
SystemTestCase::driven_byAllow 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 a
No route matcheserror. 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
HostAuthorizationmiddleware to render debug info only whenconfig.consider_all_requests_localis 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
developmentenvironment by default using theconfig.server_timingsetting and set the relevant duration metrics in theServer-TimingheaderThe 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::ParseErrorto avoid inadvertently logging the HTTP request body at thefatallevel 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#deletebut 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_hostoptions toredirect_to. Opt in to this behaviour withActionController::Base.raise_on_open_redirects = true.Gannon McGibbon
-
Deprecate
poltergeistandwebkit(capybara-webkit) driver registration for system testing (they will be removed in Rails 7.1). Addcupriteinstead.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') # => falseGavin 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 in
rescued_responses.It may be too noisy to get all backtraces logged for applications that manage uncaught exceptions via
rescued_responsesandexceptions_app.config.action_dispatch.log_rescued_responses(defaults totrue) can be set tofalsein this case, so that only exceptions not found inrescued_responseswill 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_storemethod to set HTTP cache controlno-storedirective.Tadas Sasnauskas
-
Drop support for the
SERVER_ADDRheader.Following up https://github.com/rack/rack/pull/1573 and https://github.com/rails/rails/pull/42349.
Ricardo Díaz
-
Set session options when initializing a basic session.
Gannon McGibbon
-
Add
cache_control: {}option tofresh_whenandstale?.Works as a shortcut to set
response.cache_controlwith 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_controllerinstrumentation to allow subscribers to know which controller action received unpermitted parameters.bbuchalter
-
Add
ActionController::Live#send_streamthat 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 endDHH
-
Add
ActionController::Live::Buffer#writelnto write a line to the stream with a newline included.DHH
-
ActionDispatch::Request#content_typenow returned Content-Type header as it is.Previously,
ActionDispatch::Request#content_typereturned 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_typeinstead.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_typeto returnnilwhen the request don't have aContent-Typeheader.Rafael Mendonça França
-
Fix error in
ActionController::LogSubscriberthat would happen when throwing inside a controller action.Janko Marohnić
-
Allow anything with
#to_str(likeAddressable::URI) as aredirect_tolocation.ojab
-
Change the request method to a
GETwhen passing failed requests down toconfig.exceptions_app.Alex Robbin
-
Deprecate the ability to assign a single value to
config.action_dispatch.trusted_proxiesasRemoteIpmiddleware 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_urlorblob_url_templatetorich_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_tagandrich_text_areahelpers 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 extensible
layouts/action_view/contents/_content.html.erbtemplate to encourage user-land customizations, while retaining private API control over how the rich text itself is rendered byaction_text/contents/_content.html.erbpartial.Sean Doyle
-
Add
with_all_rich_textmethod to eager load all rich text associations on a model at once.Matt Swanson, DHH
Action View
-
Support
include_hidden:option in calls toActionView::Helper::FormBuilder#file_fieldwithmultiple: trueto 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_towhen 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_nameview helper, along with theFormBuilder#field_namecounterpart:form_for @post do |f| f.field_tag :tag, name: f.field_name(:tag, multiple: true) # => <input type="text" name="post[tag][]"> endSean Doyle
-
Execute the
ActionView::Base.field_error_procwithin the context of theActionView::Baseinstance: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: falsebutton_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: falseorform_with ..., html: { action: false }form_for ..., url: falseorform_for ..., html: { action: false }form_tag falseorform_tag ..., action: falsebutton_to "...", falseorbutton_to(false) { ... }
Sean Doyle
-
Add
:day_formatoption todate_selectdate_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_tohelper to infer link name fromModel#to_swhen it is used with a single argument:link_to @profile #=> <a href="/profiles/1">Eileen</a>This assumes the model class implements a
to_smethod like this:class Profile < ApplicationRecord # ... def to_s name end endPreviously you had to supply a second argument even if the
Profilemodel implemented a#to_smethod that called thenamemethod.link_to @profile, @profile.name #=> <a href="/profiles/1">Eileen</a>Olivier Lacan
-
Support svg unpaired tags for
taghelper.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_tagproperly insertsasattributes for files withimageMIME types, such as JPG or SVG.Nate Berkopec
-
Add
weekday_options_for_selectandweekday_selecthelper methods. Also addsweekday_selecttoFormBuilder.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_secondsoption 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_codeoption tosms_tofor consistency withphone_to.Jonathan Hefner
-
OpenSSL constants are now used for Digest computations.
Dirkjan Bussink
-
The
translatehelper now passesdefaultvalues that aren't translation keys throughI18n.translatefor interpolation.Jonathan Hefner
-
Adds option
extnametostylesheet_link_tagto skip default.cssextension 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
renderlocals to be assigned to instance variables.Petrik de Heus
-
Remove legacy default
media=screenfromstylesheet_link_tag.André Luis Leal Cardoso Junior
-
Change
ActionView::Helpers::FormBuilder#buttonto transformformmethodattributes 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_toto 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_headerto allow disabling of theLinkheader being added by default when usingstylesheet_link_tagandjavascript_include_tag.Andrew White
-
The
translatehelper now resolvesdefaultvalues when anilkey is specified, instead of always returningnil.Jonathan Hefner
-
Add
config.action_view.image_loadingto configure the default value of theimage_tag:loadingoption.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#idreturns the value of the<form>element'sidattribute. With amethodargument, returns theidattribute 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_idreturns 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.attributesto 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_enqueueoption.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_performcallbacks when a previous callback was halted withthrow :abort.Rafael Mendonça França
-
Raise an
SerializationErrorinSerializer::ModuleSerializerif the module name is not present.Veerpal Brar
-
Allow a job to retry indefinitely
The
attemptsparameter of theretry_onmethod now accepts the symbol reference:unlimitedin 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 endDaniel Morton
-
Added possibility to check on
:priorityin test helper methodsassert_enqueued_withandassert_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_latercan 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,ActiveJobadapters now have the ability to raise anActiveJob::EnqueueErrorwhich will be caught and stored in the job instance so code attempting to enqueue jobs can inspect any raisedEnqueueErrorusing 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 endDaniel Morton
-
Don't log rescuable exceptions defined with
rescue_from.Hu Hailin
-
Allow
rescue_fromto rescue all exceptions.Adrianna Chang, Étienne Barrié
Active Model
-
Remove support to Marshal load Rails 5.x
ActiveModel::AttributeSetformat.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
deleteerrors fromActiveModel::Errors#messages.Rafael Mendonça França
-
Remove deprecated support to
clearerrors 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::Errorsinstances as a Hash.Rafael Mendonça França
-
Clear secure password cache if password is set to
nilBefore:
user.password = 'something' user.password = nil
user.password # => 'something'
Now:
user.password = 'something' user.password = nil
user.password # => nil
Markus Doits
-
Introduce
ActiveModel::API.Make
ActiveModel::APIthe 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_jsonforActiveModel::Dirtyobject.Exclude
mutations_from_databaseattribute 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: rangeparameter tonumericalityvalidator.Michal Papis
-
Add
localeargument toActiveModel::Name#initializeto be used to generate thesingular,plural,route_keyandsingular_route_keyvalues.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.rbwhen 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 remained
nilAndres Howard
-
#authenticatereturns false when the password is blank instead of raising an error.Muhammad Muhammad Ibrahim
-
Fix
ActiveRecord::QueryMethods#in_order_ofbehavior for integer enums.ActiveRecord::QueryMethods#in_order_ofdidn'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_onlytoupsert_allto 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_onlythat 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_attributeswere not filtered.Now, the filter attributes will be masked
[FILTERED]in the logs whenprepared_statementis 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
environmentandnamearguments 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).firstto search using non-deterministic order.Rafael Mendonça França
-
Remove deprecated rake tasks:
db:schema:load_if_rubydb:structure:dumpdb:structure:loaddb:structure:load_if_sqldb:structure:dump:#{name}db:structure:load:#{name}db:test:load_structuredb:test:load_structure:#{name}
Rafael Mendonça França
-
Remove deprecated
DatabaseConfig#configmethod.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::Baseobjects.Rafael Mendonça França
-
Remove deprecated support to quote
ActiveRecord::Baseobjects.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
:intervalcolumn is used in PostgreSQL database.Now, interval columns will return
ActiveSupport::Durationobjects instead of strings.To keep the old behavior, you can add this line to your model:
attribute :column, :stringRafael Mendonça França
-
Remove deprecated support to YAML load
ActiveRecord::Baseinstance in the Rails 4.2 and 4.1 formats.Rafael Mendonça França
-
Remove deprecated option
:spec_namein theconfigs_formethod.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_manyinversing recursion on models with recursive associations.Gannon McGibbon
-
Add
accepts_nested_attributes_forsupport fordelegated_typeclass 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: falseThe filename set in
schema_dumpwill be used by the application. If set tofalsethe 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_swappingto 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_insertsis 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_timestampsconfig, matching the behaviour ofcreate,update, etc. It can also be overridden by using therecord_timestamps:keyword argument.Note that this means
upsert_allon models withrecord_timestamps = falsewill no longer touchupdated_{at,on}automatically.Sam Bostock
-
Don't require
rolewhen passingshardtoconnected_to.connected_tocan now be called with ashardonly. Note thatroleis still inherited ifconnected_tocalls 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 = truein your application configuration. In addition aschema_cache_pathshould 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_ofdetection for associations with scopes.Automatic
inverse_ofdetection now works for associations with scopes. For example, thecommentsassociation here now automatically detectsinverse_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 endNote that the automatic detection still won't work if the inverse association has a scope. In this example a scope on the
postassociation would still prevent Rails from finding the inverse for thecommentsassociation.This will be the default for new apps in Rails 7. To opt in:
config.active_record.automatic_scope_inversing = trueDaniel Colson, Chris Bloom
-
Accept optional transaction args to
ActiveRecord::Locking::Pessimistic#with_lock#with_locknow 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) endUsing the default behavior, the transaction would fail when executing the first
INSERTstatement.By passing the
:deferrableoption to theadd_foreign_keystatement in migrations, it's possible to defer this check.add_foreign_key :aliases, :person, deferrable: truePassing
deferrable: truedoesn't change the default behavior, but allows manually deferring the check usingSET CONSTRAINTS ALL DEFERREDwithin 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: :deferredBenedikt 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_hashwill now return,
{ :user=>"user", :password=>"secret", :dbname=>"app", :adapter=>"postgresql" }Abeid Ahmed
-
PostgreSQL: support custom enum types
In migrations, use
create_enumto add a new enum type, andt.enumto 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 endEnums 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:dumpwhen using PostgreSQL >= 11. This allows loading the dump without a pgsql superuser account.Fixes #36816, #43107.
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 endMichał 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 scopesWeston Ganger
-
Use full precision for
updated_atininsert_all/upsert_allCURRENT_TIMESTAMPprovides 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_timestampfor 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,PGSSLKEYandPGSSLROOTCERTto 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.crtEnvironment variables
PGSSLMODE=verify-full PGSSLCERT=client.crt PGSSLKEY=client.key PGSSLROOTCERT=ca.crtFixes #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#updateand not also to the callbacks from the update itself.Dylan Thacker-Smith
-
Fix 2 cases that inferred polymorphic class from the association's
foreign_typeusingString#constantizeinstead of the model'spolymorphic_class_for.When updating a polymorphic association, the old
foreign_typewas not inferred correctly when:touching 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, andindexeswould 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) returnsnilif 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:nameAfter running
db:schema:load:namethe previous connection is restored.Jacopo Beschi
-
Add database config option
database_tasksIf 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 option
database_tasks: false# config/database.yml production: primary: database: my_database adapter: mysql2 animals: database: my_animals_database adapter: mysql2 database_tasks: falseWeston Ganger
-
Fix
ActiveRecord::InternalMetadatato not be broken byconfig.active_record.record_timestamps = falseSince 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 endBy default the application, controller and action details are added to the query tags:
class BooksController < ApplicationController def index @books = Book.all end endGET /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:setupandrails 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
#oror#andis 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 ASCHowever, because this functionality is built into MySQL in the form of the
FIELDfunction, that connection adapter will generate the following SQL instead:SELECT "posts".* FROM "posts" ORDER BY FIELD("posts"."id", 1, 5, 3) DESCKevin Newton
-
Fix
eager_loading?when ordering withSymbol.eager_loading?is triggered correctly when usingorderwith symbols.scope = Post.includes(:comments).order(:"comments.label") => trueJacopo Beschi
-
Two change tracking methods are added for
belongs_toassociations.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 the
schema_dumpoption:# config/database.yml production: schema_dump: falseLuis Vasconcellos, Eileen M. Uchitelle
-
Fix
eager_loading?when ordering withHashsyntax.eager_loading?is triggered correctly when usingorderwith hash syntax on an outer table.Post.includes(:comments).order({ "comments.label": :ASC }).eager_loading? # => trueJacopo Beschi
-
Move the forcing of clear text encoding to the
ActiveRecord::Encryption::Encryptor.Fixes #42699.
J Smith
-
partial_insertsis 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 = trueIf 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_columnsto 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 = trueTests 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_oneassociation after settingbelongs_toassociation tonil.After setting a
belongs_torelation toniland updating an unrelated attribute on the owner, the owner should still returnnilon thehas_onerelation.Fixes #42597.
Michiel de Mare
-
OpenSSL constants are now used for Digest computations.
Dirkjan Bussink
-
Adds support for
if_not_existstoadd_foreign_keyandif_existstoremove_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 endclass RemoveAuthorsForeignKeyFromArticles < ActiveRecord::Migration[7.0] def change remove_foreign_key :articles, :authors, if_exists: true end endRoberto 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 like
rails db:test:preparemay have been affected.Samuel Cochran
-
Set precision 6 by default for
datetimecolumns.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_encryptionthat isEncoding::UTF_8by 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"to0and will evaluate toTRUEwhich 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).firstWould 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.updatebut 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
trueif the object has been previously persisted but now it has been deleted. -
Deprecate
partial_writesin favor ofpartial_insertsandpartial_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.loadbehaves likeYAML.safe_load. To preserve compatibility, Active Record's schema cache loader andYAMLColumnnow usesYAML.unsafe_loadif available.Jean Boussier
-
ActiveRecord::Base.loggeris 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_firstfor 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_existsonadd_column.Previously, if a migration called
add_columnwith theif_not_existsoption 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
:mediumblobin the migration will be casted tobinarywhen 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 fromadd_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_oneassociations.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
has_oneassociations.Set the option on a has one through association:
class Person has_one :dog has_one :veterinarian, through: :dog, disable_joins: true endThen 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::Dotnow renders a complete set of properties when visitingArel::Nodes::SelectCore,SelectStatement,InsertStatement,UpdateStatement, andDeleteStatement, which fixes #42026. Previously, some properties were omitted.Mike Dalessio
-
Arel::Visitors::Dotnow 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_columnsto use a single SQL statement.remove_columns :my_table, :col_one, :col_twoNow results in the following SQL:
ALTER TABLE "my_table" DROP COLUMN "col_one", DROP COLUMN "col_two"Jon Dufresne
-
Ensure
has_oneautosave association callbacks get called once.Change the
has_oneautosave 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 endThen 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 wildcard
SELECT *queries, which invalidates the result of cached prepared statements and raises aPreparedStatementCacheExpirederror.When enabled, Active Record will avoid wildcards and always include column names in
SELECTqueries, which will return consistent results and avoid prepared statement errors.Before:
Book.limit(5) # SELECT * FROM books LIMIT 5After:
# 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 endBook.limit(5) # SELECT id, author_id, name, format, status, language, etc FROM books LIMIT 5Matt Duszynski
-
Allow passing SQL as
on_duplicatevalue to#upsert_allto 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
returningstatement 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 endYou can learn more in the Active Record Encryption guide.
Jorge Manrubia
-
Changed Arel predications
containsandoverlapsto usequoted_nodeso 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 StrictLoadingViolationErrorPreviously, enabling strict loading would cause any lazily loaded association to raise an error. Using
n_plus_one_onlymode 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 nilAfter this commit,
record.datetimegetsFloat::INFINITYas 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 } endBefore:
# 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 :throughassociations now load timestamps on join tables.Given this fixture:
### monkeys.yml george: name: George the Monkey fruits: apple ### fruits.yml apple: name: appleIf the join table (
fruit_monkeys) containscreated_atorupdated_atcolumns, 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 set
async_query_executortonilwhich will not initialize any executor. Ifload_asyncis 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_executorto:global_thread_pooland optionally defineconfig.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_executorcan 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
enumto 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 endAfter:
class Book < ActiveRecord::Base enum :status, [ :proposed, :written ], prefix: true, scopes: false enum :cover, [ :hard, :soft ], suffix: true, default: :hard endRyuta 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 endActive 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 100The 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#excludingmethod.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
scopingtoall_queries.Some applications may want to use the
scopingmethod but previously it only worked on certain types of queries. This change allows thescopingmethod 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 endEileen M. Uchitelle
-
ActiveRecord::Calculations.calculatecalled with:average(aliased asActiveRecord::Calculations.average) will now use column-based type casting. This means that floating-point number columns will now be aggregated asFloatand decimal columns will be aggregated asBigDecimal.Integers are handled as a special case returning
BigDecimalalways (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 # => FloatBefore this change, Rails just called
to_don 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::ClassMethodsfor documentation).Josua Schmid
-
PostgreSQL: introduce
ActiveRecord::ConnectionAdapters::PostgreSQLAdapter.datetime_type.This setting controls what native type Active Record should use when you call
datetimein a migration or schema. It takes a symbol which must correspond to one of the configuredNATIVE_DATABASE_TYPES. The default is:timestamp, meaningt.datetimein a migration will create a "timestamp without time zone" column. To use "timestamp with time zone", change this to:timestamptzin an initializer.You should run
bin/rails db:migrateto rebuild your schema.rb if you change this.Alex Ghiculescu
-
PostgreSQL: handle
timestamp with time zonecolumns correctly inschema.rb.Previously they dumped as
t.datetime :column_name, now they dump ast.timestamptz :column_name, and are created astimestamptzcolumns 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 named
ApplicationRecordcan now set a specific class to be theprimary_abstract_class.class PrimaryApplicationRecord self.primary_abstract_class endWhen an application boots it automatically connects to the primary or first database in the database configuration file. In a multiple database application that then call
connects_toneeds to know that the default connection is the same as theApplicationRecordconnection. 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_flagsandstructure_load_flagsflags. 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 adapter
ActiveRecord::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_loadingmode 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#soleand#find_sole_byto 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 aboveAsherah Connor
-
Makes
ActiveRecord::AttributeMethods::Queryrespect 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_iddefined by it does not work when the foreign_key does not end withid. This change fixes it by taking into accountprimary_keyandforeign_keyin the options.Ryota Egusa
-
Expose an
invert_wheremethod 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
falseto :polymorphic option ofbelongs_to.Previously, passing
falsewould trigger the option validation logic to throw an error saying :polymorphic would not be a valid option.glaszig
-
Remove deprecated
databasekwarg 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_scopeon all queries.Previously, a
default_scopewould only run on select or insert queries. In some cases, like non-Rails tenant sharding solutions, it may be desirable to rundefault_scopeon 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_queriesoption to the default scope definition.class Article < ApplicationRecord default_scope -> { where(blog_id: Current.blog.id) }, all_queries: true endEileen M. Uchitelle
-
Add
where.associatedto 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_associationandcreate_association) onhas_one :throughassociations.Santiago Perez Perret
Active Storage
-
Support transforming empty-ish
has_many_attachedvalue into[](e.g.[""]).@user.highlights = [""] @user.highlights # => []Sean Doyle
-
Add ActiveStorage::Blob.composeto 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/javascriptwill 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 = trueto 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
vipsthe default variant processor for new apps.See the upgrade guide for instructions on converting from
mini_magicktovips.mini_magickis not deprecated, existing apps can keep using it.Breno Gazzola
-
Deprecate
ActiveStorage::Current.hostin favor ofActiveStorage::Current.url_optionswhich accepts a host, protocol and port.Santiago Bartesaghi
-
Allow using IAM when signing URLs with GCS.
gcs: service: GCS ... iam: trueRRethy
-
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_urlin favor ofurl.Santiago Bartesaghi
-
Add support of
strict_loading_by_defaulttoActiveStorage::Representationscontrollers.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
metadataattribute of video blobs has a new boolean key namedvideothat is set totrueif the file has an video channel andfalseif it doesn't.Breno Gazzola
-
Deprecate usage of
purgeandpurge_laterfrom the association extension.Jacopo Beschi
-
Passing extra parameters in
ActiveStorage::Blob#urlto S3 Client.This allows calls of
ActiveStorage::Blob#urlto 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-Controlon files uploaded to GCS.gcs: service: GCS ... cache_control: "public, max-age=3600"maleblond
-
The parameters sent to
ffmpegfor 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_recordsmethod to eager load all variant records on an attachment at once.with_attached_imagescope now eager loads variant records if using variant tracking.Alex Ghiculescu
-
Add metadata value for presence of audio channel in video blobs.
The
metadataattribute of video blobs has a new boolean key namedaudiothat is set totrueif the file has an audio channel andfalseif 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_infor 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::VariantRecordclass. This makesActiveStorage::VariantRecordconsistent withActiveStorage::BlobandActiveStorage::Attachmentthat already have load hooks.Brendon Muir
-
ActiveStorage::PreviewErroris raised when a previewer is unable to generate a preview image.Alex Robbin
-
Add
ActiveStorage::Streamingmodule that can be included in a controller to get access to#send_blob_stream, which wraps the newActionController::Base#send_streammethod 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 endDHH
-
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_proxyrails_blob_pathandrails_representation_pathwill generate proxy URLs by default.Ali Ismayilov
-
Declare
ActiveStorage::FixtureSetandActiveStorage::FixtureSet.blobto improve fixture integration.Sean Doyle
Active Support
-
Fix
ActiveSupport::Duration.buildto support negative values.The algorithm to collect the
partsof theActiveSupport::Durationignored the sign of thevalueand 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_sin favor of#to_formatted_sinArray,Range,Date,DateTime,Time,BigDecimal,Floatand,Integer.Rafael Mendonça França
-
Document
ActiveSupport::Testing::Deprecation.Sam Bostock & Sam Jordan
-
Add
Pathname#existence.Pathname.new("file").existence&.readTimo 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_optionswithout a&blockargument returns theActiveSupport::OptionMergerinstance.Sean Doyle
-
Rails.application.executorhooks 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::DescendantsTrackernow mostly delegate toClass#descendantson Ruby 3.1Ruby now provides a fast
Class#descendantsmakingActiveSupport::DescendantsTrackermostly useless.As a result the following methods are deprecated:
ActiveSupport::DescendantsTracker.direct_descendantsActiveSupport::DescendantsTracker#direct_descendants
Jean Boussier
-
Fix the
Digest::UUID.uuid_from_hashbehavior 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_uuidsoption totrueand 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 the
Digest::UUIDextension 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::Dependenciesno longer installs aconst_missinghook. Before this, you could push to the autoload paths and have constants autoloaded. This feature, known as theclassicautoloader, has been removed.Xavier Noria
-
Private internal classes of
ActiveSupport::Dependencieshave been deleted, likeActiveSupport::Dependencies::Reference,ActiveSupport::Dependencies::Blamable, and others.Xavier Noria
-
The private API of
ActiveSupport::Dependencieshas been deleted. That includes methods likehook!,unhook!,depend_on,require_or_load,mechanism, and many others.Xavier Noria
-
Improves the performance of
ActiveSupport::NumberHelperformatters by avoiding the use of exceptions as flow control.Mike Dalessio
-
Removed rescue block from
ActiveSupport::Cache::RedisCacheStore#handle_exceptionPreviously, if you provided a
error_handlertoredis_cache_store, any errors thrown by the error handler would be rescued and logged only. Removed therescueclause fromhandle_exceptionto 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.warna no-op:config.active_support.report_deprecations = falseThis is the default in production for new apps. It is the equivalent to:
config.active_support.deprecation = :silence config.active_support.disallowed_deprecation = :silencebut 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 = 100It's also configurable at the test case level:
class ActiveSupport::TestCase parallelize threshold: 100 endJorge Manrubia
-
OpenSSL constants are now used for Digest computations.
Dirkjan Bussink
-
TimeZone.iso8601now accepts valid ordinal values similar to Ruby'sDate._iso8601method. A valid ordinal value will be converted to an instance ofTimeWithZoneusing the:yearand:ydayfragments 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#changeand methods that call it (e.g.Time#advance) will now return aTimewith 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::MissingKeyErrorwhen theRAILS_MASTER_KEYenvironment 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 } } endGeorge Claghorn
-
Deprecate
ActiveSupport::SafeBuffer's incorrect implicit conversion of objects into string.Except for a few methods like
String#%, objects must implement#to_strto be implicitly converted to a String in string operations. In some circumstancesActiveSupport::SafeBufferwas 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.enccould be accessed with method calls. Now any key can.For example, given these secrets:
aws: access_key_id: 123 secret_access_key: 345Rails.application.credentials.aws.access_key_idwill now return the same thing asRails.application.credentials.aws[:access_key_id].Alex Ghiculescu
-
Added a faster and more compact
ActiveSupport::Cacheserialization format.It can be enabled with
config.active_support.cache_format_version = 7.0orconfig.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#partsand remove writer methods.Durations are meant to be value objects and should not be mutated.
Andrew White
-
Fix
ActiveSupport::TimeZone#utc_to_localwith fractional seconds.When
utc_to_local_returns_utc_offset_timesis false and the time instance had fractional seconds the new UTC time instance was out by a factor of 1,000,000 as theTime.utcconstructor takes a usec value and not a fractional second value.Andrew White
-
Add
expires_atargument toActiveSupport::Cachewriteandfetchto 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.nameso that from Rails 7.1 it will use the default implementation.Andrew White
-
Deprecates Rails custom
Enumerable#sumandArray#sumin 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]].sumAlberto 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_WORKERSis present and set to a value greater than 1.Ricardo Díaz
-
Fix proxying keyword arguments in
ActiveSupport::CurrentAttributes.Marcin Kołodziej
-
Add
Enumerable#maximumandEnumerable#minimumto 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) # => 15This also allows passing enumerables to
fresh_whenandstale?in Action Controller. See PR #41404 for an example.Ayrton De Craene
-
ActiveSupport::Cache::MemCacheStorenow accepts an explicitnilfor itsaddressesargument.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 DalliThis helps those migrating from
:dalli_store, where an explicitnilwas permitted.Michael Overmeyer
-
Add
Enumerable#in_order_ofto put an Enumerable in a certain order by a key.DHH
-
ActiveSupport::Inflector.camelizebehaves expected when provided a symbol:upperor:lowerargument. MatchesString#camelizebehavior.Alex Ghiculescu
-
Raises an
ArgumentErrorwhen the first argument ofActiveSupport::Notification.subscribeis invalid.Vipul A M
-
HashWithIndifferentAccess#deep_transform_keysnow returns aHashWithIndifferentAccessinstead of aHash.Nathaniel Woodthorpe
-
Consume dalli’s
cache_nilsconfiguration asActiveSupport::Cache'sskip_nilwhen usingMemCacheStore.Ritikesh G
-
Add
RedisCacheStore#statsmethod similar toMemCacheStore#stats. Callsredis#infointernally.Ritikesh G
Guides
-
The autoloading guide for
zeitwerkmode has been revised.Xavier Noria
-
The autoloading guide for
classicmode has been deleted.Xavier Noria
Railtie
-
Allow localhost with a port by default in development
[Fixes: #43864]
-
Remove deprecated
configindbconsole.Rafael Mendonça França
-
Change default
X-XSS-Protectionheader 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.rborconfig/initializers/cookies_serializer.rbThe 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
debuggem, 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.zeitwerkis the only available autoloading mode.Xavier Noria
-
config.autoload_once_pathscan be configured in the body of the application class defined inconfig/application.rbor 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 the
Rails.autoloaders.onceautoloader, 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 a
to_prepareblock. 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 that
config.autoload_once_pathsis a subset ofconfig.autoload_paths. The former are managed by theonceautoloader. Themainautoloader 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 newcommand to help.*Petrik de Heus
-
Fix
config_forerror 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.jsonnow 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 Authorno 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:cleardeletes also files and directories intmp/storage.George Claghorn
-
Fix compatibility with
psych >= 4.Starting in Psych 4.0.0
YAML.loadbehaves likeYAML.safe_load. To preserve compatibilityRails.application.config_fornow usesYAML.unsafe_loadif available.Jean Boussier
-
Allow loading nested locales in engines.
Gannon McGibbon
-
Ensure
Rails.application.config_foralways cast hashes toActiveSupport::OrderedOptions.Jean Boussier
-
Remove
Rack::Runtimefrom 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:updateno 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.benchmarkgives you a quick way to measure and log the execution time taken by a block:def test_expensive_stuff Rails.benchmark("test_expensive_stuff") { ... } endThis functionality was available in some contexts only before.
Simon Perepelitsa
-
Applications generated with
--skip-sprocketsno longer getapp/assets/config/manifest.jsandapp/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