Rails 7.2 is out!
There has been close to 2,500 commits made by over 400 contributors since Rails 7.1, so this release is packed with new features and improvements like better production defaults, dev containers, new guides design, and more!
Read all the details here.
Happy 78th independence day to all the Pakistani (and Indian) readers. This is
Sajjad Umar, your own Desi Developer, with all the juicy updates in Ruby on Rails world. Let’s jump right in!
New Design For Rails Guide
The design of the guides has remained largely untouched since 2009 - a point which hasn’t gone unnoticed.
The new design of the rails guide is now live!
Read all the details here.
Nominations open for the 2024 Rails Luminary Awards
Last year the Rails Foundation started the Rails Luminary Awards acknowledging people who’ve contributed to the Rails ecosystem and community with exceptional code, documentation, enthusiasm, or assistance, thereby helping others do more, learn more, or be inspired.
Do you know someone who has consistently gone above and beyond to help others, who has shaped discussions, answered countless questions, triaged bugs, added particularly helpful features, or introduced us all to innovative new ideas?
Nominate these exceptional individuals who you believe deserve to be recognized.
Read all the details here.
More Guides PR for Review
More Guides related PRs are open for community review if you are good at Rails Routing and Active Record Associations, please review and submit your feedback here:
I’ve started a new series on my Medium account where I share all the things I build in my part-time. Checkout the first episode here:
https://medium.com/@sajjadumar/building-a-saas-episode-01-7bfa17bfe2f4
Added a basic sessions generator
This PR adds a basic sessions generator to get people started with their own authentication system. This is not intended to be an all-singing, all-dancing answer to every possible authentication concern. It's merely intended to illuminate the basic path, and reveal that rolling your own authentication system is not some exotic adventure.
Read all the details here.
Added script folder and generator
This Pull Request changes the Rails app generator to create a new script default directory that can hold one-off scripts, data migration scripts, cleanup scripts, benchmark scripts, etc. This PR also adds a basic script generator to create such scripts.
Read all the details here.
ActiveRecord: Raise specific exception when a connection is not defined
This Pull Request has been created to make providing programmatic access to details about the requested shard/role easier.
This Pull Request introduces a more specific exception
ConnectionNotDefined
as a subclass of the previously-raisedConnectionNotEstablished
. The new exception is used to handle cases where a requested database connection pool has not been found.The
retrieve_connection_pool
method in connection_handler.rb has been modified to provide more specific error messages reflecting if we're missing a shard and/or a role.Test cases have been updated to reflect these changes.
Read all the details here.
Added not-null modifier to migrations
This change adds a not-null modifier to migrations, which we can now specify using a !
after column types:
# 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
Read all the details here.
Removed channels from default app/ structure
Now that Hotwire is the default, the majority of apps won't need custom channels. And those that do can get the files back via the generator.
Read all the details here.
Dropped default permissions policy initializer
This change drops the rarely used default permissions_policy
configuration files. The configuration can be added back as needed referring to the documentation of permissions_policy
instead.
Read all the details here.
Dropped Hash#except
core extension
Rails 8.0 will be Ruby 3.1 or greater only except natively got added in Ruby 3.0 so this is dead code now.
https://docs.ruby-lang.org/en/3.1/Hash.html#method-i-except
This dead code has been removed.
Read all the details here.
ActiveModel: Introduced ActiveModel::AttributeAssignment#attribute_writer_missing
This PR introduced the ActiveModel::AttributeAssignment#attribute_writer_missing
method to 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'"
By default, classes that do not override #attribute_writer_missing
will raise an ActiveModel::UnknownAttributeError
.
Read all the details here.
Added cvv
and cvc
as default parameters to filter out in new apps
Generally, you should avoid posting credit card details directly to your server and instead use a payment processor like Stripe or Braintree. However, if you accidentally include a user's credit card number in a form submission, those details may be logged by default, even if your server doesn't process them. This situation can lead to unintentionally "storing card data," which brings additional legal obligations to ensure secure handling.
This pull request adds cvv
and cvc
to the default parameters filtered by ActiveSupport::ParameterFilter
for new applications. This ensures that parameters with these names won't be logged by default. Note that this change only applies to new apps; existing apps remain unaffected.
Read all the details here.
SQLite
transaction now defaults to IMMEDIATE mode
As SQLite's popularity grows as a production database engine for Rails applications, so does the need for robust and resilient default configuration. One of the most common issues faced when using SQLite in a Rails application is the occasional ActiveRecord::StatementInvalid
(SQLite3::BusyException
: database is locked) exceptions. These occur when a DEFERRED
transaction attempts to acquire the SQLite database lock in the middle of a transaction once hitting a write query while another connection holds the database lock. Since this occurs in the middle of a transaction, SQLite
does not attempt to retry to transaction by calling the set busy_handler/busy_timeout callback, but instead immediately errors with a busy exception.
This PR updates the SQLite adapter to use IMMEDIATE mode whenever possible in order to improve concurrency support and avoid busy exceptions.
Read all the details here.
Reallowed setting secret_key_base
to nil
when local
This commit restores that behavior so that applications can continue to set secret_key_base
unconditionally since the nil value will end up getting replaced by the generated local secret anyway.
Read all the details here.
ActiveRecord
: Now Support batching using custom columns
This pull request adds support to Active Record batching to be used with custom columns.
Product.in_batches(cursor: [:shop_id, :id]) do |relation|
# do something with relation
end
Read all the details here.
Deprecated multiple path route mapping
This PR deprecates using multiple paths on route mappings:
Rails.application.routes.draw do
get "/users", "/other_path/users", "/another_path/users", to: "users#index"
end
Instead, you can write as follows which is simple and more readable:
Rails.application.routes.draw do
get "/users", to: "users#index"
get "/other_path/users", to: "users#index"
get "/another_path/users", to: "users#index"
end
Read all the details here.
Added password reset to authentication generator
This pull request adds a basic password reset flow to the new Rails generator to show the use of signed ids with a mailer.
Also, the generator was renamed to “authentication
”.
Read all the details here.
Implemented new maintenance policy
The main changes are:
Releases are maintained by a pre-defined, fixed period. One year for bug fixes and two years for security fixes.
The distinction between severe security issues and regular security issues is removed.
NPM versioning is updated to match not use the pre-release
-
separator.
Read all the details here.
Added a default password reset token to has_secure_password
This PR adds a default configuration for a 15-minute password reset token 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)
Read all the details here.
Implemented the bin/rails
boot command
The new bin/rails
boot command starts the application and then exits. It supports the standard -e/--environment
options, making it useful for testing the boot process of a Rails app or for benchmarking purposes.
Read all the details here.
Renamed some helper methods
Some of the helper method names were changed, keeping the old names as aliases.
Renamed
check_box
tocheckbox
Renamed
text_area
totextarea
Renamed
rich_text_area
torich_textarea
Read all the details here and here.
Docker: Generate errors when running a Docker build with warnings
Docker introduced Docker build checks and by default, running a Docker build with warnings will not cause the build to fail (return a non-zero exit code). To raise errors on warnings # check=error=true declaration should be added to the Dockerfile, and this pull request did that.
Read all the details here.
Changed ActiveModel
human_attribute_name
to raise an error
When config.i18n.raise_on_missing_translations = true
, controllers and views raise an error on missing translations. However, models won't. This PR changes models to raise an error when raise_on_missing_translations
is true.
Read all the details here.
Deprecated hash key path mapping
This pull request deprecates drawing routes with hash key paths to make routing faster.
# Before
get "/users" => "users#index"
post "/logout" => :sessions
mount MyApp => "/my_app"
# After
get "/users", to: "users#index"
post "/logout", to: "sessions#logout"
mount MyApp, at: "/my_app"
Read all the details here.
Rails 8 will use Thruster by default
Thruster is an asset compression and caching proxy with X-Sendfile acceleration that speeds up simple production-ready deployments of Rails applications. It runs alongside the Puma
and usually behind the Kamal 2 proxy, which offers HTTP/2
and SSL auto-certificates, to help your app run efficiently and safely on the open Internet.
Rails 8 will configure the use of Thruster in the Dockerfile by default.
Read all the details here.
Allowed disable_extension
to be called with schema-qualified name
This change allows disable_extension
to be called with schema-qualified name for PostgreSQL.
Read all the details here.
allow_browser
now allow bots
The allow_browser feature blocks requests with user agents that don’t match a specific set of browser versions. This runs the risk of preventing sites from being crawled by some search engines.
This change fixes this behavior by bypassing these version restrictions for certain crawlers and bots.
Read all the details here.
Route mapping scope lookups are now faster
This Pull Request changes the scope implementation. Scopes are backed by an array of hashes, but we could make lookup faster by just merging inherited values into the immediate hash. This is from needless iterations for deeply nested routes.
Read all the details here.
Automatic detection of processor count in default puma config is now optional and non-default
Using Concurrent.available_processor_count helper by default in puma.rb might result in incorrect configurations on some cloud hosts with shared CPUs or platforms that inaccurately report CPU counts.
This Pull Request changes:
Make
puma.rb
spawn only 1 worker by default ifWEB_CONCURRENCY
is not setModify default
puma.rb
to offer "auto
" as an option forWEB_CONCURRENCY
Enhance comment in default
deploy.yml
to offer "auto
" as an option forWEB_CONCURRENCY
Update note to
tuning_performance_for_deployment.md
to explain theWEB_CONCURRENCY
Read all the details here.
Removed redundant Puma configuration settings
This Pull Request removes the following redundant environment settings in puma.rb
:
# Specifies the `environment` that Puma will run in.
rails_env = ENV.fetch("RAILS_ENV", "development")
environment rails_env
case rails_env
when "production"
preload_app!
when "development"
# Specifies a very generous `worker_timeout` so that the worker
# isn't killed by Puma when suspended by a debugger.
worker_timeout 3600
end
Read all the details here.
Improved default action mailer configuration
This PR adds a few improvements to the default Action Mailer configuration setup:
Suggest a default SMTP server configuration in a comment in production.rb
Set a default example.com host for mailer links in production too.
Use the same comment style in all the env settings for mailer host.
Read all the details here.
That is it for this month, until then! ✌️