Hey, Rubyists welcome to the September edition of Ruby on Rails Monthly. This newsletter is a few days late because I was away to perform Umrah.
Upcoming newsletters will be published on the usual date (15th of every month). With that being said, let’s jump right in!
This is
your own Desi Developer back with all the updates in the Ruby on Rails world.First Beta Version of Rails 7.1 is out
Dockerfiles, BYO Authentication, More Async Queries, and more!
There has been over five thousand commits made by over 800 contributors since Rails 7.0, so this release is packed with new features and improvements.
The main highlights of the announcements are:
Dockerfiles for new applications
Improvements in building your own authentication
More async queries for Active Record
Built-in support for the Trilogy MySQL adapter
Support for composite primary keys in Active Record
Enqueueing massive amounts of jobs with
perform_all_later
Introduced
config.autoload_lib
andconfig.autoload_lib_once
for Enhanced AutoloadingSupport to Bun
Read all the details here.
Turbo 8 is dropping TypeScript
A lot of conversations and criticism around this one throughout the rails community, but DHH has said goodbye to TypeScript (Link to the PR).
Read all the details here.
Rails now ignore all env files except templates (finally!)
This will help people avoid checking in .env files with potentially sensitive tokens.
Read all the details here.
Rails now raises error when generating attribute with dangerous names
Generating a model with attributes named hash
or save
now raise an error, instead of generating a migration with an invalid attribute.
Read all the details here.
Explicit primary_key:
option now always take priority in associations
This PR fixes the issue where the primary_key: option was ignored if the associated model had a query_constraints
configured. Now primary_key:
option always takes priority and only if there is no primary_key:
option, the query_constraints
are used to determine the association_primary_key
value.
Read all the details here.
Encryption: support support_unencrypted_data
at a per-attribute
level
If ActiveRecord::Encryption.config.support_unencrypted_data == true, this allows you to do:
class User < ActiveRecord::Base
encrypts :name, deterministic: true, support_unencrypted_data: false
encrypts :email, deterministic: true
end
Now only the email
column will allow unencrypted data (and if extend_queries
is true
, only email queries will get extended).
Read all the details here.
Added support for if_not_exists
when adding a check constraint
The add_check_constraint method now accepts an if_not_exists option. If set to true an error won't be raised if the check constraint already exists. In addition, if_exists and if_not_exists options are transposed if set when reversing remove_check_constraint and add_check_constraint. This enables the simple creation of idempotent, non-transactional migrations.
Read all the details here.
Instrument Active Record transactions
This PR adds a new transaction.active_record
event that should provide a more reliable solution for these various use cases. It includes the connection in the payload (useful, for example, in differentiating transactions to different databases).
Read all the details here.
Added "Testing View Partials" section to the Testing Guides
A “Testing View Partials” section is added to the guides that expand upon the variety of tooling available to tests that inherit from ActionView::TestCase
.
Read all the details here.
Fixed unscope
not working when where by tripe dot range
This change fixes unscope
not working in specific case for triple dot range. For example:
Read all the details here.
Made enums validatable without raising error
This Pull Request adds :validate
option for enums
If you want the enum value to be validated before saving, use the option :validate
:
class Conversation < ApplicationRecord
enum :status, %i[active archived], validate: true
end
conversation = Conversation.new
conversation.status = :unknown
conversation.valid? # => false
conversation.status = nil
conversation.valid? # => false
conversation.status = :active
conversation.valid? # => true
It is also possible to pass additional validation options:
class Conversation < ApplicationRecord
enum :status, %i[active archived], validate: { allow_nil: true }
end
conversation = Conversation.new
conversation.status = :unknown
conversation.valid? # => false
conversation.status = nil
conversation.valid? # => true
conversation.status = :active
conversation.valid? # => true
Otherwise, ArgumentError will raise (standard current behavior):
class Conversation < ApplicationRecord
enum :status, %i[active archived]
end
conversation = Conversation.new
conversation.status = :unknown # 'unknown' is not a valid status (ArgumentError)
Read all the details here.
Added Bun support
As mentioned before in the 7.1 beta announcement; Bun support has been added to rails. Bun is a new and viable alternative to the node.js runtime, yarn package manager, and esbuild bundler. Bun's primary differentiating characteristic is speed. It's often many multiple times faster than node.js and friends.
Since most vanilla Rails projects are looking to simply sprinkle a little JS here and there (but sometimes want a bit better more of the JS ecosystem than the import-maps provide) Bun is a really good fit and can be easily adopted by new rails projects.
Read all the details here.
Added a dedicated guide for composite primary keys
Added a dedicated guide for composite primary key usage. Most of this content was compiled from other guides/documentation for composite primary keys.
Read all the details here.
Also added support composite foreign keys via migration helpers in another PR.
Read all the details here.
Infer primary_key::id
on associations with composite primary key models
Before implementing this modification, the process for establishing associations in models with composite primary keys would require the following steps:
class Order
self.primary_key = [:shop_id, :id]
has_many :order_agreements, primary_key: :id
end
class OrderAgreement
belongs_to :order, primary_key: :id
end
After this change, the primary_key
option no longer needs to be specified:
class Order
self.primary_key = [:shop_id, :id]
has_many :order_agreements
end
class OrderAgreement
belongs_to :order
end
Read all the details here.
Fixed: simple_format
with blank wrapper_tag
option returns plain html tag
This PR updates the behavior of the simple_format
helper, If the user passes nil
or an empty string as a value for wrapper_tag
it defaults to use the <p>
tag for wrapping.
Read all the details here.
Changed has_secure_token
default to on::initialize
Following the recent updates, the declarations for has_secure_token can now be set up to run within an "after_initialize
" callback. This commit introduces a new default behavior in Rails 7.1: generating all has_secure_token
values during the initialization of their associated models.
Read all the details here.
Added after_discard
method to ActiveJob
This Pull Request changes no existing behavior but adds after_discard
.
after_discard
is called in any situation where the job is about to be discarded due to a failure. Those cases are:
When an exception is being raised by the job without retry_on or discard_on used
When an exception is handled by discard_on (with or without a block)
When an exception is handled by retry_on (with or without a block), but only after the job has run out of retries for that exception
If multiple exceptions are raised when running the after_discard blocks, then only the last exception will be raised. This behavior ensures that all blocks will be run despite exceptions
Read all the details here.
Rails now use SecureRandom.alphanumeric for SecureRandom.base36/base58
In Ruby 3.3, a new feature was introduced that enables the passing of a character list to SecureRandom.alphanumeric
. This enhancement now applies SecureRandom.alphanumeric
for SecureRandom.base36/base58
, replacing the previously complex usage of SecureRandom.random_number/random_bytes
. This results in a slightly faster solution.
Read all the details here.
Deprecated read_attribute(:id)
returning the primary key
This PR deprecates read_attribute(:id)
returning the primary key if the model's primary key is not the id column. Starting in Rails 7.2, read_attribute(:id)
should return the value of the id column.
This commit also changes read_attribute(:id)
for composite primary key models to return the value of the id column, not the composite primary key.
Read all the details here.
Deprecated passing rewhere
to merge
The usage of Relation#merge(rewhere: true)
is no longer necessary, as it has been the default behavior since Rails 7.0. This modification serves as a deprecation notice, and attempting to set the rewhere
option will result in a warning starting in Rails 7.2 and will eventually lead to an error.
Read all the details here.
Fixed change_column
not setting precision for sqlite
This commit changes the change_column method to replace the existing column without using the existing options. This ensures that precision: 6 is set consistently across adapters when change_column
is used to create a datetime column.
Read all the details here.
MRSK
renamed to Kamal
Due to a trademark claim, the MRSK project has been renamed to Kamal after the ancient Arab navigational tool. The new executable is now kamal
and all env variables are prefixed with KAMAL_*.
The new website going forward will be live at https://kamal-deploy.org.
Read all the details here.
Fixed host display when X_FORWARDED_HOST
authorized
This commit addresses the issue by tweaking how the blocked host is displayed. Instead of always displaying Request#host
(which will return X_FORWARDED_HOST
when present whether or not that's the host being blocked), each host being blocked will be displayed on its own.
Read all the details here.
Added pattern-matching support for response.parsed_body
This commit adds coverage for those new assertions and incorporates examples into the documentation for the response.parsed_body
method.
Read all the details here.
Added support for Playwright as a driver for system tests
This PR adds support for the Playwright driver to Rails.
Read all the details here.
Added generatation of config.autoload_lib(...)
for new apps
With this patch, newly generated config/application.rb now include
config.autoload_lib(ignore: %w(assets tasks))
In practice, this means that new 7.1 applications autoload from lib out of the box.
Read all the details here.
Added an option to start rails console in sandbox mode by default
sandbox_by_default
option is added to start rails console in sandbox mode by default. With this option turned on, --no-sandbox
must be specified to start rails in non-sandbox mode.
Read all the details here.
Allowed redefining to_param
delimiter using param_delimiter
This commit allows customizing the delimiter used by to_param when to_key returns multiple value. This unblocks supporting more varieties of composite primary key types in Active Record.
Read all the details here.
Sorted mailers on mailer preview page alphabetically
This PR ensures that the list of mailers on the mailer preview page are always returned in alphabetical order (by their titleized name) to make it easier to scan the list and find a specific mailer.
Read all the details here.
Use alias_attribute
to provide id_value
alias for id attribute
Extends on #48533.
You can now use alias_attribute
to provide a uid alias for the id attribute. That was one of the primary use cases described in the above pull request; as such, we've decided to provide it out of the box in Rails.
Read all the details here.
That is it for this month; stay curious, keep coding, and mark your calendars (for the next edition) because the Ruby adventure never stops. Until then, happy coding, fellow Rails enthusiasts! ✌️
Keep reading with a 7-day free trial
Subscribe to Ruby on Rails - Monthly to keep reading this post and get 7 days of free access to the full post archives.