What's new in Rails 7.1
Update:
Rails 7.1 Beta 1 is released on September 13, 2023.
Rails 7.1 is released on October 5, 2023.
Let’s see what is new in rails 7.1
Dockerfile
Rails will now auto generate docker related files in the application.
Dockerfile
.dockerignore
bin/docker-entrypoint
Build and run your application using docker
docker build -t app .
docker volume create app-storage
docker run --rm -it -v app-storage:/rails/storage -p 3000:3000 --env RAILS_MASTER_KEY=<your-config-master-key> app
BYO Authentication
New addition normalizes
for attribute normalization.
Normalization is applied when the attribute is assigned or updated, and the normalized value will be persisted to the database.
class User < ApplicationRecord
normalizes :email, with: -> email { email.strip.downcase }
normalizes :phone, with: -> phone {
phone.delete("^0-9").delete_prefix("1")
}
end
# Normalize email address before creating a user
user = User.create(email: " CRUISE-CONTROL@EXAMPLE.COM\n")
user.email # => "cruise-control@example.com"
# Normalize email address before finding a user
user = User.find_by(email: "\tCRUISE-CONTROL@EXAMPLE.COM ")
user.email # => "cruise-control@example.com"
user.email_before_type_cast # => "cruise-control@example.com"
# Database query
User.where(email: "\tCRUISE-CONTROL@EXAMPLE.COM ").count
# => 1
# Normalize value on the fly
User.normalize_value_for(:phone, "+1 (555) 867-5309")
# => "5558675309"
Enhancement to has_secure_password
to verify the current password while updating the password.
# Schema: User(email:string, password_digest:string)
class User < ActiveRecord::Base
has_secure_password
end
user = User.new(
email: "johndoe@example.com",
password: "john#123",
password_confirmation: "john#123"
)
user.save
# => true
user.update(password: "john@123", password_challenge: "")
# => false, challenge doesn't authenticate
user.update(password: "john@123", password_challenge: "john#123")
# => true
Async queries
Intorduction of new Async queries.
Async queries return ActiveRecord::Promise
object.
Supported methods:
async_count
async_sum
async_minimum
async_maximum
async_average
async_pluck
async_pick
async_find_by_sql
async_count_by_sql
> promise = Product.where(state: 'active').async_count
Product Count (0.4ms) SELECT COUNT(*) FROM "products" WHERE "products"."state" = $1 [["state", "active"]]
# => #<ActiveRecord::Promise status=complete>
> promise.value
# => 16
> promise = Product.where(state: 'active').async_sum(:price)
Product Sum (0.2ms) SELECT SUM("products"."price") FROM "products" WHERE "products"."state" = $1 [["state", "active"]]
# => #<ActiveRecord::Promise status=complete>
> promise.value
# => 491.0
> promise = Product.where(state: 'active').async_minimum(:price)
Product Minimum (0.3ms) SELECT MIN("products"."price") FROM "products" WHERE "products"."state" = $1 [["state", "active"]]
# => #<ActiveRecord::Promise status=complete>
> promise.value
# => 5.0
> promise = Product.where(state: 'active').async_maximum(:price)
Product Maximum (0.3ms) SELECT MAX("products"."price") FROM "products" WHERE "products"."state" = $1 [["state", "active"]]
# => #<ActiveRecord::Promise status=complete>
> promise.value
# => 100.0
> promise = Product.where(state: 'active').async_average(:price)
Product Average (0.3ms) SELECT AVG("products"."price") FROM "products" WHERE "products"."state" = $1 [["state", "active"]]
# => #<ActiveRecord::Promise status=complete>
> promise.value
# => 30.6875
Enqueue multiple jobs at once using perform_all_later
Enqueue multiple jobs simultaneously with the help of perform_all_later
.
This new addition allows you to enqueue multiple jobs without triggering the callbacks.
# Enqueueing individual jobs
ActiveJob.perform_all_later(
MyJob.new("hello", 42),
MyJob.new("world", 0)
)
# Enqueueing an array of jobs
user_jobs = User.pluck(:id).map { |id| UserJob.new(user_id: id) }
ActiveJob.perform_all_later(user_jobs)
Composite Primary Keys
You can add composite primary keys now.
# app/models/book.rb
class Book < ApplicationRecord
self.primary_key = [:author_id, :id]
belongs_to :author
end
If you don’t want to modify the database schema,
you can make use of query_constraints
as virtual primary key
.
class Book < ActiveRecord::Base
query_constraints :author_id, :id
end
Support for Bun
Bun has got popular!
so rails decided to
add support for bun
in jsbundling-rails
Now, you can generate a new rails application using Bun as your javascript runtime.
$ rails new blog --javascript=bun
OR if you want to add bun in an existing application
$ bin/rails javascript:install:bun