Happy New Year, everyone! 🎉 This is Sajjad Umar, kicking off 2025 with a brand-new edition of Ruby on Rails Monthly.
A new year brings fresh opportunities, exciting updates, and plenty to explore in the world of Rails. We've got a packed edition to start the year strong, so let’s dive right in!
Colorized console prompt on non standard environments
Currently, the Rails console prompt is colored according to the following rules:
on dev, the prompt becomes blue
on test, the prompt becomes blue
on prod, the prompt becomes red
on non-standard environments (like staging), the prompt is not colored
This PR adds colors to the console prompts for custom environments.
Read all the details here.
Have you checked out my book, Ruby on Rails for Agile Web Development? Whether you're a beginner or looking to refine your skills, this guide is packed with practical insights, hands-on examples, and pro tips to help you build modern, robust web applications with ease.
👉 Grab your copy now and start 2025 by leveling up your development game!
CI: Introduced RAILS_MASTER_KEY placeholder
The existing CI templates do not work as expected if custom credentials are utilized, or if config.require_master_key
is enabled.
ActiveSupport::MessageEncryptor::InvalidMessage: ActiveSupport::MessageEncryptor::InvalidMessage
This PR improves existing CI templates by adding an environment variable to store the RAILS_MASTER_KEY
which should be stored as a secret.
Read all the details here.
ActiveSupport::Configurable Deprecated
ActiveSupport::Configurable
was only used once by rails internally, that only used occurrence has been replaced by class_attribute and delegate to deprecate ActiveSupport::Configurable.
Deprecated String#mb_chars and AS::Multibyte::Chars
This PR depicates String#mb_chars
and AS::Multibyte::Chars
.
Read all the details here.
Fixed running individual app:update commands
This fixes a regression introduced in #53647, where the individual app:update
commands (like app:update:configs
or app:update:bin
) can no longer be ran on their own, as they require the app to be loaded and it no longer is.
Read all the details here.
Fixed: ArgumentErrors raised during template rendering
Issue #52227 pointed out that any argument error in a template with strict locals would be swallowed and replaced by an exception with unrelated backtrace, which made debugging templates difficult.
Now after this PR, any ArgumentError
unrelated to strict locals is reraised, preserving the original backtrace for developers.
Also note that ActionView::StrictLocalsError
is a subclass of ArgumentError
, so any existing code that rescues ArgumentError
will continue to work.
Read all the details here.
Action View: fixed local variable access in layouts
This was originally broken, reportedly, in Rails 5.1 in d6bac04 which dropped the locals
keys from some of the layout lookup methods to optimize the template resolver cache.
In the meantime, the template resolver cache was discarded in Rails 7.0 in 4db7ae5, and was replaced by a FileSystemResolver cache that does not use the locals in the lookup key (because it's storing unbound templates).
So this fix is, essentially, to pass keys through the many layers of the layout resolver/renderer stack to make sure that when the unbound template is found and #bind_locals
is called on it, it's bound with the proper set of local variable names.
Read all the details here.
Sort table columns by name when dumping schema
The table columns inside schema.rb are now sorted alphabetically. Previously, they’d be sorted by creation order, which can cause merge conflicts when two branches modify the same table concurrently.
Read all the details here.
Rails now use the given form
in html_options
for the hidden field in collection_check_boxes
Fixes the issue mentioned in this PR collection_check_boxes hidden field ignores :form option.
Check all the details here.
Don't load ActiveStorage::Blob when validating the service
For tasks like assets:precompile
that don't need ActiveStorage, we should not be loading the entire Active Storage behavior just to be able to validate the service configuration since Active Storage might be misconfigured for that task.
Load configured Active Storage plugins during boot
Previously, the parts of Active Storage using ruby-vips, mini_magick, or
image_processing would try to load gems only when used. This strategy works
well because it allows apps that don't need these features to easily
ignore them and not have to depend on gems they don't need.
However, the downside to this strategy is that it requires loading
code during requests and that it moves potential error messages into request
logs instead of those errors being immediately visible on boot.
This PR addresses these issues by restructing how the Vips and Image
Magick transformers/analyzers are organized so that they will be loaded
(if configured) on boot along with whatever dependencies they need.
Read more about it here.
Updated NotificationAssertions's assert_notifcation to match against payload subsets and return matched notification
ActiveSupport::Testing::NotificationAssertions’s assert_notification now matches against payload subsets by default.
Previously the following assertion would fail due to excess key values in the notification payload. Now with payload subset matching, it will pass.
assert_notification("post.submitted", title: "Cool Post") do
ActiveSupport::Notifications.instrument("post.submitted", title: "Cool Post", body: "Cool Body")
end
Additionally, you can now persist a matched notification for more customized assertions.
notification = assert_notification("post.submitted", title: "Cool Post") do
ActiveSupport::Notifications.instrument("post.submitted", title: "Cool Post", body: Body.new("Cool Body"))
end
assert_instance_of(Body, notification.payload[:body])
Read all the details here.
Handle new records in #increment!
Similar to #update_columns, an exception will be raised on records that haven't been saved yet or were destroyed.
Read all the details here.
Removed monkey patches of Range#each and Range#step
This PR removes monkey patches of Range#each
and Range#step
.
Read all the details here.
Introduced versions formatter for the schema dumper
You can now customize how the schema dumper formats version information in the structure.sql
file. By default, versions are sorted in descending order, which can lead to frequent merge conflicts at the top of the list in large teams. With the new feature, you can provide a custom formatter with your own sorting logic, such as sorting by hash values of the versions, significantly reducing the likelihood of conflicts.
Read all the details here.
Replaced SyntaxTree with Prism in rail_inspector
Now that Prism has been stable for a while and is the default parser in Ruby 3.4, it is probably time to use it in rail_inspector
.
This PR replaces SyntaxTree with Prism.
Read all the details here.
Fixed setting to_time_preserves_timezone from new_framework_defaults_8_0.rb
This PR fixes:
Setting active_support.to_time_preserves_timezone
in new_frameworks_default_8_0.rb
does not work because the active_support.to_time_preserves_timezone
initializer runs before the load_config_initializers
that loads the config/initializers
files.
Read all the details here.
Handle path_params gracefully when a user sends ?path_params=string
When url contains the query part ?path_params=string it is now ignored and does not error.
Read all the details here.
Fixed #to_query to not include = for nil values
Having a nil
value in the parameters hash should result in a key with no value in the query string.
Currently, a nil
value results in the same query string as a blank string, namely key=
.
# Before
nil.to_query("key") #=> key=
# After
nil.to_query("key") #=> key
Prevented Active Storage Blob from autosaving Attachments
This change should not impact existing applications but will ensure that adding an attachment to a record doesn't automatically save it, causing other callbacks to run unexpectedly.
Read all the details here.
Added an option to ensure uniqueness of newly generated session IDs in Session::CacheStore
This new option was added for situations where guaranteeing the uniqueness of the session ID is required.
Read all the details here.
Allow to tag serialized attributes as comparable
A not rare issue when working with serialized attributes is that the serialized representation of an object can change over time. Either because you are migrating from one serializer to the other (e.g. YAML to JSON or to msgpack), or because the serializer used subtly changed it's output.
When this sorts of thing happen, you end up with lots of records that report being changed even though they aren't, which in the best case leads to a lot more writes to the database and in the worst case lead to nasty bugs.
his option was added to ease migration between different coders.
Refer to the API docs for more information.
Read all the details here.
And that is all for this month's edition - I will be back with more updates next month until then ✌🏻