Skip to content

8.0.0

Latest
Compare
Choose a tag to compare
@rafaelfranca rafaelfranca released this 07 Nov 22:29
· 425 commits to main since this release
v8.0.0
dd8f718

Active Support

  • Remove deprecated support to passing an array of strings to ActiveSupport::Deprecation#warn.

    Rafael Mendonça França

  • Remove deprecated support to setting attr_internal_naming_format with a @ prefix.

    Rafael Mendonça França

  • Remove deprecated ActiveSupport::ProxyObject.

    Rafael Mendonça França

  • Don't execute i18n watcher on boot. It shouldn't catch any file changes initially,
    and unnecessarily slows down boot of applications with lots of translations.

    Gannon McGibbon, David Stosik

  • Fix ActiveSupport::HashWithIndifferentAccess#stringify_keys to stringify all keys not just symbols.

    Previously:

    { 1 => 2 }.with_indifferent_access.stringify_keys[1] # => 2

    After this change:

    { 1 => 2 }.with_indifferent_access.stringify_keys["1"] # => 2

    This change can be seen as a bug fix, but since it behaved like this for a very long time, we're deciding
    to not backport the fix and to make the change in a major release.

    Jean Boussier

  • Include options when instrumenting ActiveSupport::Cache::Store#delete and ActiveSupport::Cache::Store#delete_multi.

    Adam Renberg Tamm

  • Print test names when running rails test -v for parallel tests.

    John Hawthorn, Abeid Ahmed

  • Deprecate Benchmark.ms core extension.

    The benchmark gem will become bundled in Ruby 3.5

    Earlopain

  • ActiveSupport::TimeWithZone#inspect now uses ISO 8601 style time like Time#inspect

    John Hawthorn

  • ActiveSupport::ErrorReporter#report now assigns a backtrace to unraised exceptions.

    Previously reporting an un-raised exception would result in an error report without
    a backtrace. Now it automatically generates one.

    Jean Boussier

  • Add escape_html_entities option to ActiveSupport::JSON.encode.

    This allows for overriding the global configuration found at
    ActiveSupport.escape_html_entities_in_json for specific calls to to_json.

    This should be usable from controllers in the following manner:

    class MyController < ApplicationController
      def index
        render json: { hello: "world" }, escape_html_entities: false
      end
    end

    Nigel Baillie

  • Raise when using key which can't respond to #to_sym in EncryptedConfiguration.

    As is the case when trying to use an Integer or Float as a key, which is unsupported.

    zzak

  • Deprecate addition and since between two Time and ActiveSupport::TimeWithZone.

    Previously adding time instances together such as 10.days.ago + 10.days.ago or 10.days.ago.since(10.days.ago) produced a nonsensical future date. This behavior is deprecated and will be removed in Rails 8.1.

    Nick Schwaderer

  • Support rfc2822 format for Time#to_fs & Date#to_fs.

    Akshay Birajdar

  • Optimize load time for Railtie#initialize_i18n. Filter I18n.load_paths passed to the file watcher to only those
    under Rails.root. Previously the watcher would grab all available locales, including those in gems
    which do not require a watcher because they won't change.

    Nick Schwaderer

  • Add a filter option to in_order_of to prioritize certain values in the sorting without filtering the results
    by these values.

    Igor Depolli

  • Improve error message when using assert_difference or assert_changes with a
    proc by printing the proc's source code (MRI only).

    Richard Böhme, Jean Boussier

  • Add a new configuration value :zone for ActiveSupport.to_time_preserves_timezone and rename the previous true value to :offset. The new default value is :zone.

    Jason Kim, John Hawthorn

  • Align instrumentation payload[:key] in ActiveSupport::Cache to follow the same pattern, with namespaced and normalized keys.

    Frederik Erbs Spang Thomsen

  • Fix travel_to to set usec 0 when with_usec is false and the given argument String or DateTime.

    mopp

Active Model

  • Add :except_on option for validations. Grants the ability to skip validations in specified contexts.

    class User < ApplicationRecord
        #...
        validates :birthday, presence: { except_on: :admin }
        #...
    end
    
    user = User.new(attributes except birthday)
    user.save(context: :admin)

    Drew Bragg

  • Make ActiveModel::Serialization#read_attribute_for_serialization public

    Sean Doyle

  • Add a default token generator for password reset tokens when using has_secure_password.

    class User < ApplicationRecord
      has_secure_password
    end
    
    user = User.create!(name: "david", password: "123", password_confirmation: "123")
    token = user.password_reset_token
    User.find_by_password_reset_token(token) # returns user
    
    # 16 minutes later...
    User.find_by_password_reset_token(token) # returns nil
    
    # raises ActiveSupport::MessageVerifier::InvalidSignature since the token is expired
    User.find_by_password_reset_token!(token)

    DHH

  • Add a load hook active_model_translation for ActiveModel::Translation.

    Shouichi Kamiya

  • Add raise_on_missing_translations option to ActiveModel::Translation.
    When the option is set, human_attribute_name raises an error if a translation of the given attribute is missing.

    # ActiveModel::Translation.raise_on_missing_translations = false
    Post.human_attribute_name("title")
    => "Title"
    
    # ActiveModel::Translation.raise_on_missing_translations = true
    Post.human_attribute_name("title")
    => Translation missing. Options considered were: (I18n::MissingTranslationData)
        - en.activerecord.attributes.post.title
        - en.attributes.title
    
                raise exception.respond_to?(:to_exception) ? exception.to_exception : exception
                      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

    Shouichi Kamiya

  • Introduce ActiveModel::AttributeAssignment#attribute_writer_missing

    Provide instances with an opportunity to gracefully handle assigning to an
    unknown attribute:

    class Rectangle
      include ActiveModel::AttributeAssignment
    
      attr_accessor :length, :width
    
      def attribute_writer_missing(name, value)
        Rails.logger.warn "Tried to assign to unknown attribute #{name}"
      end
    end
    
    rectangle = Rectangle.new
    rectangle.assign_attributes(height: 10) # => Logs "Tried to assign to unknown attribute 'height'"

    Sean Doyle

Active Record

  • Fix support for query_cache: false in database.yml.

    query_cache: false would no longer entirely disable the Active Record query cache.

    zzak

  • NULLS NOT DISTINCT works with UNIQUE CONSTRAINT as well as UNIQUE INDEX.

    Ryuta Kamizono

  • The db:prepare task no longer loads seeds when a non-primary database is created.

    Previously, the db:prepare task would load seeds whenever a new database
    is created, leading to potential loss of data if a database is added to an
    existing environment.

    Introduces a new database config property seeds to control whether seeds
    are loaded during db:prepare which defaults to true for primary database
    configs and false otherwise.

    Fixes #53348.

    Mike Dalessio

  • PG::UnableToSend: no connection to the server is now retryable as a connection-related exception

    Kazuma Watanabe

  • Fix strict loading propagation even if statement cache is not used.

    Ryuta Kamizono

  • Allow rename_enum accepts two from/to name arguments as rename_table does so.

    Ryuta Kamizono

  • Remove deprecated support to setting ENV["SCHEMA_CACHE"].

    Rafael Mendonça França

  • Remove deprecated support to passing a database name to cache_dump_filename.

    Rafael Mendonça França

  • Remove deprecated ActiveRecord::ConnectionAdapters::ConnectionPool#connection.

    Rafael Mendonça França

  • Remove deprecated config.active_record.sqlite3_deprecated_warning.

    Rafael Mendonça França

  • Remove deprecated config.active_record.warn_on_records_fetched_greater_than.

    Rafael Mendonça França

  • Remove deprecated support for defining enum with keyword arguments.

    Rafael Mendonça França

  • Remove deprecated support to finding database adapters that aren't registered to Active Record.

    Rafael Mendonça França

  • Remove deprecated config.active_record.allow_deprecated_singular_associations_name.

    Rafael Mendonça França

  • Remove deprecated config.active_record.commit_transaction_on_non_local_return.

    Rafael Mendonça França

  • Fix incorrect SQL query when passing an empty hash to ActiveRecord::Base.insert.

    David Stosik

  • Allow to save records with polymorphic join tables that have inverse_of
    specified.

    Markus Doits

  • Fix association scopes applying on the incorrect join when using a polymorphic has_many through:.

    Joshua Young

  • Allow ActiveRecord::Base#pluck to accept hash arguments with symbol and string values.

    Post.joins(:comments).pluck(:id, comments: :id)
    Post.joins(:comments).pluck("id", "comments" => "id")

    Joshua Young

  • Make Float distinguish between float4 and float8 in PostgreSQL.

    Fixes #52742

    Ryota Kitazawa, Takayuki Nagatomi

  • Allow drop_table to accept an array of table names.

    This will let you to drop multiple tables in a single call.

    ActiveRecord::Base.lease_connection.drop_table(:users, :posts)

    Gabriel Sobrinho

  • Add support for PostgreSQL IF NOT EXISTS via the :if_not_exists option
    on the add_enum_value method.

    Ariel Rzezak

  • When running db:migrate on a fresh database, load the databases schemas before running migrations.

    Andrew Novoselac, Marek Kasztelnik

  • Fix an issue where .left_outer_joins used with multiple associations that have
    the same child association but different parents does not join all parents.

    Previously, using .left_outer_joins with the same child association would only join one of the parents.

    Now it will correctly join both parents.

    Fixes #41498.

    Garrett Blehm

  • Deprecate unsigned_float and unsigned_decimal short-hand column methods.

    As of MySQL 8.0.17, the UNSIGNED attribute is deprecated for columns of type FLOAT, DOUBLE,
    and DECIMAL. Consider using a simple CHECK constraint instead for such columns.

    https://dev.mysql.com/doc/refman/8.0/en/numeric-type-syntax.html

    Ryuta Kamizono

  • Drop MySQL 5.5 support.

    MySQL 5.5 is the only version that does not support datetime with precision,
    which we have supported in the core. Now we support MySQL 5.6.4 or later, which
    is the first version to support datetime with precision.

    Ryuta Kamizono

  • Make Active Record asynchronous queries compatible with transactional fixtures.

    Previously transactional fixtures would disable asynchronous queries, because transactional
    fixtures impose all queries use the same connection.

    Now asynchronous queries will use the connection pinned by transactional fixtures, and behave
    much closer to production.

    Jean Boussier

  • Deserialize binary data before decrypting

    This ensures that we call PG::Connection.unescape_bytea on PostgreSQL before decryption.

    Donal McBreen

  • Ensure ActiveRecord::Encryption.config is always ready before access.

    Previously, ActiveRecord::Encryption configuration was deferred until ActiveRecord::Base
    was loaded. Therefore, accessing ActiveRecord::Encryption.config properties before
    ActiveRecord::Base was loaded would give incorrect results.

    ActiveRecord::Encryption now has its own loading hook so that its configuration is set as
    soon as needed.

    When ActiveRecord::Base is loaded, even lazily, it in turn triggers the loading of
    ActiveRecord::Encryption, thus preserving the original behavior of having its config ready
    before any use of ActiveRecord::Base.

    Maxime Réty

  • Add TimeZoneConverter#== method, so objects will be properly compared by
    their type, scale, limit & precision.

    Address #52699.

    Ruy Rocha

  • Add support for SQLite3 full-text-search and other virtual tables.

    Previously, adding sqlite3 virtual tables messed up schema.rb.

    Now, virtual tables can safely be added using create_virtual_table.

    Zacharias Knudsen

  • Support use of alternative database interfaces via the database_cli ActiveRecord configuration option.

    Rails.application.configure do
      config.active_record.database_cli = { postgresql: "pgcli" }
    end

    T S Vallender

  • Add support for dumping table inheritance and native partitioning table definitions for PostgeSQL adapter

    Justin Talbott

  • Add support for ActiveRecord::Point type casts using Hash values

    This allows ActiveRecord::Point to be cast or serialized from a hash
    with :x and :y keys of numeric values, mirroring the functionality of
    existing casts for string and array values. Both string and symbol keys are
    supported.

    class PostgresqlPoint < ActiveRecord::Base
      attribute :x, :point
      attribute :y, :point
      attribute :z, :point
    end
    
    val = PostgresqlPoint.new({
      x: '(12.34, -43.21)',
      y: [12.34, '-43.21'],
      z: {x: '12.34', y: -43.21}
    })
    ActiveRecord::Point.new(12.32, -43.21) == val.x == val.y == val.z

    Stephen Drew

  • Replace SQLite3::Database#busy_timeout with #busy_handler_timeout=.

    Provides a non-GVL-blocking, fair retry interval busy handler implementation.

    Stephen Margheim

  • SQLite3Adapter: Translate SQLite3::BusyException into ActiveRecord::StatementTimeout.

    Matthew Nguyen

  • Include schema name in enable_extension statements in db/schema.rb.

    The schema dumper will now include the schema name in generated
    enable_extension statements if they differ from the current schema.

    For example, if you have a migration:

    enable_extension "heroku_ext.pgcrypto"
    enable_extension "pg_stat_statements"

    then the generated schema dump will also contain:

    enable_extension "heroku_ext.pgcrypto"
    enable_extension "pg_stat_statements"

    Tony Novak

  • Fix ActiveRecord::Encryption::EncryptedAttributeType#type to return
    actual cast type.

    Vasiliy Ermolovich

  • SQLite3Adapter: Bulk insert fixtures.

    Previously one insert command was executed for each fixture, now they are
    aggregated in a single bulk insert command.

    Lázaro Nixon

  • PostgreSQLAdapter: Allow disable_extension to be called with schema-qualified name.

    For parity with enable_extension, the disable_extension method can be called with a schema-qualified
    name (e.g. disable_extension "myschema.pgcrypto"). Note that PostgreSQL's DROP EXTENSION does not
    actually take a schema name (unlike CREATE EXTENSION), so the resulting SQL statement will only name
    the extension, e.g. DROP EXTENSION IF EXISTS "pgcrypto".

    Tony Novak

  • Make create_schema / drop_schema reversible in migrations.

    Previously, create_schema and drop_schema were irreversible migration operations.

    Tony Novak

  • Support batching using custom columns.

    Product.in_batches(cursor: [:shop_id, :id]) do |relation|
      # do something with relation
    end

    fatkodima

  • Use SQLite IMMEDIATE transactions when possible.

    Transactions run against the SQLite3 adapter default to IMMEDIATE mode to improve concurrency support and avoid busy exceptions.

    Stephen Margheim

  • Raise specific exception when a connection is not defined.

    The new ConnectionNotDefined exception provides connection name, shard and role accessors indicating the details of the connection that was requested.

    Hana Harencarova, Matthew Draper

  • Delete the deprecated constant ActiveRecord::ImmutableRelation.

    Xavier Noria

  • Fix duplicate callback execution when child autosaves parent with has_one and belongs_to.

    Before, persisting a new child record with a new associated parent record would run before_validation,
    after_validation, before_save and after_save callbacks twice.

    Now, these callbacks are only executed once as expected.

    Joshua Young

  • ActiveRecord::Encryption::Encryptor now supports a :compressor option to customize the compression algorithm used.

    module ZstdCompressor
      def self.deflate(data)
        Zstd.compress(data)
      end
    
      def self.inflate(data)
        Zstd.decompress(data)
      end
    end
    
    class User
      encrypts :name, compressor: ZstdCompressor
    end

    You disable compression by passing compress: false.

    class User
      encrypts :name, compress: false
    end

    heka1024

  • Add condensed #inspect for ConnectionPool, AbstractAdapter, and
    DatabaseConfig.

    Hartley McGuire

  • Add .shard_keys, .sharded?, & .connected_to_all_shards methods.

    class ShardedBase < ActiveRecord::Base
        self.abstract_class = true
    
        connects_to shards: {
          shard_one: { writing: :shard_one },
          shard_two: { writing: :shard_two }
        }
    end
    
    class ShardedModel < ShardedBase
    end
    
    ShardedModel.shard_keys => [:shard_one, :shard_two]
    ShardedModel.sharded? => true
    ShardedBase.connected_to_all_shards { ShardedModel.current_shard } => [:shard_one, :shard_two]

    Nony Dutton

  • Add a filter option to in_order_of to prioritize certain values in the sorting without filtering the results
    by these values.

    Igor Depolli

  • Fix an issue where the IDs reader method did not return expected results
    for preloaded associations in models using composite primary keys.

    Jay Ang

  • Allow to configure strict_loading_mode globally or within a model.

    Defaults to :all, can be changed to :n_plus_one_only.

    Garen Torikian

  • Add ActiveRecord::Relation#readonly?.

    Reflects if the relation has been marked as readonly.

    Theodor Tonum

  • Improve ActiveRecord::Store to raise a descriptive exception if the column is not either
    structured (e.g., PostgreSQL +hstore+/+json+, or MySQL +json+) or declared serializable via
    ActiveRecord.store.

    Previously, a NoMethodError would be raised when the accessor was read or written:

    NoMethodError: undefined method `accessor' for an instance of ActiveRecord::Type::Text
    

    Now, a descriptive ConfigurationError is raised:

    ActiveRecord::ConfigurationError: the column 'metadata' has not been configured as a store.
      Please make sure the column is declared serializable via 'ActiveRecord.store' or, if your
      database supports it, use a structured column type like hstore or json.
    

    Mike Dalessio

  • Fix inference of association model on nested models with the same demodularized name.

    E.g. with the following setup:

    class Nested::Post < ApplicationRecord
      has_one :post, through: :other
    end

    Before, #post would infer the model as Nested::Post, but now it correctly infers Post.

    Joshua Young

  • Add public method for checking if a table is ignored by the schema cache.

    Previously, an application would need to reimplement ignored_table? from the schema cache class to check if a table was set to be ignored. This adds a public method to support this and updates the schema cache to use that directly.

    ActiveRecord.schema_cache_ignored_tables = ["developers"]
    ActiveRecord.schema_cache_ignored_table?("developers")
    => true

    Eileen M. Uchitelle

Action View

  • Remove deprecated support to passing a content to void tag elements on the tag builder.

    Rafael Mendonça França

  • Remove deprecated support to passing nil to the model: argument of form_with.

    Rafael Mendonça França

  • Enable DependencyTracker to evaluate renders with trailing interpolation.

    <%= render "maintenance_tasks/runs/info/#{run.status}" %>

    Previously, the DependencyTracker would ignore this render, but now it will
    mark all partials in the "maintenance_tasks/runs/info" folder as
    dependencies.

    Hartley McGuire

  • Rename text_area methods into textarea

    Old names are still available as aliases.

    Sean Doyle

  • Rename check_box* methods into checkbox*.

    Old names are still available as aliases.

    Jean Boussier

Action Pack

  • Fix routes with :: in the path.

    Rafael Mendonça França

  • Maintain Rack 2 parameter parsing behaviour.

    Matthew Draper

  • Remove Rails.application.config.action_controller.allow_deprecated_parameters_hash_equality.

    Rafael Mendonça França

  • Improve ActionController::TestCase to expose a binary encoded request.body.

    The rack spec clearly states:

    The input stream is an IO-like object which contains the raw HTTP POST data.
    When applicable, its external encoding must be “ASCII-8BIT” and it must be opened in binary mode.

    Until now its encoding was generally UTF-8, which doesn't accurately reflect production
    behavior.

    Jean Boussier

  • Update ActionController::AllowBrowser to support passing method names to :block

    class ApplicationController < ActionController::Base
      allow_browser versions: :modern, block: :handle_outdated_browser
    
      private
        def handle_outdated_browser
          render file: Rails.root.join("public/custom-error.html"), status: :not_acceptable
        end
    end

    Sean Doyle

  • Raise an ArgumentError when invalid :only or :except options are passed into #resource and #resources.

    Joshua Young

  • Fix non-GET requests not updating cookies in ActionController::TestCase.

    Jon Moss, Hartley McGuire

  • Update ActionController::Live to use a thread-pool to reuse threads across requests.

    Adam Renberg Tamm

  • Introduce safer, more explicit params handling method with params#expect such that
    params.expect(table: [ :attr ]) replaces params.require(:table).permit(:attr)

    Ensures params are filtered with consideration for the expected
    types of values, improving handling of params and avoiding ignorable
    errors caused by params tampering.

    # If the url is altered to ?person=hacked
    # Before
    params.require(:person).permit(:name, :age, pets: [:name])
    # raises NoMethodError, causing a 500 and potential error reporting
    
    # After
    params.expect(person: [ :name, :age, pets: [[:name]] ])
    # raises ActionController::ParameterMissing, correctly returning a 400 error

    You may also notice the new double array [[:name]]. In order to
    declare when a param is expected to be an array of parameter hashes,
    this new double array syntax is used to explicitly declare an array.
    expect requires you to declare expected arrays in this way, and will
    ignore arrays that are passed when, for example, pet: [:name] is used.

    In order to preserve compatibility, permit does not adopt the new
    double array syntax and is therefore more permissive about unexpected
    types. Using expect everywhere is recommended.

    We suggest replacing params.require(:person).permit(:name, :age)
    with the direct replacement params.expect(person: [:name, :age])
    to prevent external users from manipulating params to trigger 500
    errors. A 400 error will be returned instead, using public/400.html

    Usage of params.require(:id) should likewise be replaced with
    params.expect(:id) which is designed to ensure that params[:id]
    is a scalar and not an array or hash, also requiring the param.

    # Before
    User.find(params.require(:id)) # allows an array, altering behavior
    
    # After
    User.find(params.expect(:id)) # expect only returns non-blank permitted scalars (excludes Hash, Array, nil, "", etc)

    Martin Emde

  • System Testing: Disable Chrome's search engine choice by default in system tests.

    glaszig

  • Fix Request#raw_post raising NoMethodError when rack.input is nil.

    Hartley McGuire

  • Remove racc dependency by manually writing ActionDispatch::Journey::Scanner.

    Gannon McGibbon

  • Speed up ActionDispatch::Routing::Mapper::Scope#[] by merging frame hashes.

    Gannon McGibbon

  • Allow bots to ignore allow_browser.

    Matthew Nguyen

  • Deprecate drawing routes with multiple paths to make routing faster.
    You may use with_options or a loop to make drawing multiple paths easier.

    # Before
    get "/users", "/other_path", to: "users#index"
    
    # After
    get "/users", to: "users#index"
    get "/other_path", to: "users#index"

    Gannon McGibbon

  • Make http_cache_forever use immutable: true

    Nate Matykiewicz

  • Add config.action_dispatch.strict_freshness.

    When set to true, the ETag header takes precedence over the Last-Modified header when both are present,
    as specified by RFC 7232, Section 6.

    Defaults to false to maintain compatibility with previous versions of Rails, but is enabled as part of
    Rails 8.0 defaults.

    heka1024

  • Support immutable directive in Cache-Control

    expires_in 1.minute, public: true, immutable: true
    # Cache-Control: public, max-age=60, immutable

    heka1024

  • Add :wasm_unsafe_eval mapping for content_security_policy

    # Before
    policy.script_src "'wasm-unsafe-eval'"
    
    # After
    policy.script_src :wasm_unsafe_eval

    Joe Haig

  • Add display_capture and keyboard_map in permissions_policy

    Cyril Blaecke

  • Add connect route helper.

    Samuel Williams

Active Job

  • Remove deprecated config.active_job.use_big_decimal_serializer.

    Rafael Mendonça França

  • Deprecate sucker_punch as an adapter option.

    If you're using this adapter, change to adapter: async for the same functionality.

    Dino Maric, zzak

  • Use RAILS_MAX_THREADS in ActiveJob::AsyncAdapter. If it is not set, use 5 as default.

    heka1024

Action Mailer

  • No changes.

Action Cable

  • Add an identifier to the event payload for the ActiveSupport::Notification transmit_subscription_confirmation.action_cable and transmit_subscription_rejection.action_cable.

    Keith Schacht

Active Storage

  • Deprecate ActiveStorage::Service::AzureStorageService.

    zzak

  • Improve ActiveStorage::Filename#sanitized method to handle special characters more effectively.
    Replace the characters "*?<> with - if they exist in the Filename to match the Filename convention of Win OS.

    Luong Viet Dung(Martin)

  • Improve InvariableError, UnpreviewableError and UnrepresentableError message.

    Include Blob ID and content_type in the messages.

    Petrik de Heus

  • Mark proxied files as immutable in their Cache-Control header

    Nate Matykiewicz

Action Mailbox

  • No changes.

Action Text

  • Dispatch direct-upload events on attachment uploads

    When using Action Text's rich textarea, it's possible to attach files to the
    editor. Previously, that action didn't dispatch any events, which made it hard
    to react to the file uploads. For instance, if an upload failed, there was no
    way to notify the user about it, or remove the attachment from the editor.

    This commits adds new events - direct-upload:start, direct-upload:progress,
    and direct-upload:end - similar to how Active Storage's direct uploads work.

    Matheus Richard, Brad Rees

  • Add store_if_blank option to has_rich_text

    Pass store_if_blank: false to not create ActionText::RichText records when saving with a blank attribute, such as from an optional form parameter.

    class Message
      has_rich_text :content, store_if_blank: false
    end
    
    Message.create(content: "hi") # creates an ActionText::RichText
    Message.create(content: "") # does not create an ActionText::RichText

    Alex Ghiculescu

  • Strip content attribute if the key is present but the value is empty

    Jeremy Green

  • Rename rich_text_area methods into rich_textarea

    Old names are still available as aliases.

    Sean Doyle

  • Only sanitize content attribute when present in attachments.

    Petrik de Heus

Railties

  • Fix incorrect database.yml with skip_solid.

    Joé Dupuis

  • Set Regexp.timeout to 1s by default to improve security over Regexp Denial-of-Service attacks.

    Rafael Mendonça França

  • Remove deprecated support to extend Rails console through Rails::ConsoleMethods.

    Rafael Mendonça França

  • Remove deprecated file rails/console/helpers.

    Rafael Mendonça França

  • Remove deprecated file rails/console/app.

    Rafael Mendonça França

  • Remove deprecated config.read_encrypted_secrets.

    Rafael Mendonça França

  • Add Kamal support for devcontainers

    Previously generated devcontainer could not use docker and therefore Kamal.

    Joé Dupuis

  • Exit rails g with code 1 if generator could not be found.

    Previously rails g returned 0, which would make it harder to catch typos in scripts calling rails g.

    Christopher Özbek

  • Remove require_* statements from application.css to align with the transition from Sprockets to Propshaft.

    With Propshaft as the default asset pipeline in Rails 8, the require_tree and require_self clauses in application.css are no longer necessary, as they were specific to Sprockets. Additionally, the comment has been updated to clarify that CSS precedence now follows standard cascading order without automatic prioritization by the asset pipeline.

    Eduardo Alencar

  • Do not include redis by default in generated Dev Containers.

    Now that applications use the Solid Queue and Solid Cache gems by default, we do not need to include redis
    in the Dev Container. We will only include redis if --skip-solid is used when generating an app that uses
    Active Job or Action Cable.

    When generating a Dev Container for an existing app, we will not include redis if either of the solid gems
    are in use.

    Andrew Novoselac

  • Use Solid Cable as the default Action Cable adapter in production, configured as a separate queue database in config/database.yml. It keeps messages in a table and continuously polls for updates. This makes it possible to drop the common dependency on Redis, if it isn't needed for any other purpose. Despite polling, the performance of Solid Cable is comparable to Redis in most situations. And in all circumstances, it makes it easier to deploy Rails when Redis is no longer a required dependency for Action Cable functionality.

    DHH

  • Use Solid Queue as the default Active Job backend in production, configured as a separate queue database in config/database.yml. In a single-server deployment, it'll run as a Puma plugin. This is configured in config/deploy.yml and can easily be changed to use a dedicated jobs machine.

    DHH

  • Use Solid Cache as the default Rails.cache backend in production, configured as a separate cache database in config/database.yml.

    DHH

  • Add Rails::Rack::SilenceRequest middleware and use it via config.silence_healthcheck_path = path
    to silence requests to "/up". This prevents the Kamal-required health checks from clogging up
    the production logs.

    DHH

  • Introduce mariadb-mysql and mariadb-trilogy database options for rails new

    When used with the --devcontainer flag, these options will use mariadb as the database for the
    Dev Container. The original mysql and trilogy options will use mysql. Users who are not
    generating a Dev Container do not need to use the new options.

    Andrew Novoselac

  • Deprecate ::STATS_DIRECTORIES.

    The global constant STATS_DIRECTORIES has been deprecated in favor of
    Rails::CodeStatistics.register_directory.

    Add extra directories with Rails::CodeStatistics.register_directory(label, path):

    require "rails/code_statistics"
    Rails::CodeStatistics.register_directory('My Directory', 'path/to/dir')

    Petrik de Heus

  • Enable query log tags by default on development env

    This can be used to trace troublesome SQL statements back to the application
    code that generated these statements. It is also useful when using multiple
    databases because the query logs can identify which database is being used.

    Matheus Richard

  • Defer route drawing to the first request, or when url_helpers are called

    Executes the first routes reload in middleware, or when a route set's
    url_helpers receives a route call / asked if it responds to a route.
    Previously, this was executed unconditionally on boot, which can
    slow down boot time unnecessarily for larger apps with lots of routes.

    Environments like production that have config.eager_load = true will
    continue to eagerly load routes on boot.

    Gannon McGibbon

  • Generate form helpers to use textarea* methods instead of text_area* methods

    Sean Doyle

  • Add authentication generator to give a basic start to an authentication system using database-tracked sessions and password reset.

    Generate with...

    bin/rails generate authentication
    

    Generated files:

    app/models/current.rb
    app/models/user.rb
    app/models/session.rb
    app/controllers/sessions_controller.rb
    app/controllers/passwords_controller.rb
    app/mailers/passwords_mailer.rb
    app/views/sessions/new.html.erb
    app/views/passwords/new.html.erb
    app/views/passwords/edit.html.erb
    app/views/passwords_mailer/reset.html.erb
    app/views/passwords_mailer/reset.text.erb
    db/migrate/xxxxxxx_create_users.rb
    db/migrate/xxxxxxx_create_sessions.rb
    test/mailers/previews/passwords_mailer_preview.rb
    

    DHH

  • Add not-null type modifier to migration attributes.

    Generating with...

    bin/rails generate migration CreateUsers email_address:string!:uniq password_digest:string!
    

    Produces:

    class CreateUsers < ActiveRecord::Migration[8.0]
      def change
        create_table :users do |t|
          t.string :email_address, null: false
          t.string :password_digest, null: false
    
          t.timestamps
        end
        add_index :users, :email_address, unique: true
      end
    end

    DHH

  • Add a script folder to applications, and a scripts generator.

    The new script folder is meant to hold one-off or general purpose scripts,
    such as data migration scripts, cleanup scripts, etc.

    A new script generator allows you to create such scripts:

    bin/rails generate script my_script
    bin/rails generate script data/backfill
    

    You can run the generated script using:

    bundle exec ruby script/my_script.rb
    bundle exec ruby script/data/backfill.rb
    

    Jerome Dalbert, Haroon Ahmed

  • Deprecate bin/rake stats in favor of bin/rails stats.

    Juan Vásquez

  • Add internal page /rails/info/notes, that displays the same information as bin/rails notes.

    Deepak Mahakale

  • Add Rubocop and GitHub Actions to plugin generator.
    This can be skipped using --skip-rubocop and --skip-ci.

    Chris Oliver

  • Use Kamal for deployment by default, which includes generating a Rails-specific config/deploy.yml.
    This can be skipped using --skip-kamal. See more: https://kamal-deploy.org/

    DHH

Guides

  • The guide Classic to Zeitwerk HOWTO that documented how to migrate from
    the classic autoloader to Zeitwerk has been deleted.

    The last version of this guide can be found
    here,
    in case you need it.

    Petrik de Heus