Computer >> Hướng Dẫn Máy Tính >  >> Lập Trình >> Ruby

Rails 7: Tính Năng & Cải Tiến Quan Trọng Trước Khi Ra Mắt

Rails 7 sắp ra mắt. Chưa có release date chính thức, nhưng dự kiến trước Giáng sinh. Phiên bản mới nhất lúc viết: 7.0.0.rc1 (release candidate đầu tiên). Basecamp, HEY, Github, Shopify đã chạy Rails 7 alpha production, nên RC cũng ổn định.

Bài này xem xét features và changes chính của Rails 7.

Không Cần Node Và Webpack

Đúng như bạn đọc! JavaScript trong Rails 7 không còn yêu cầu NodeJS hay Webpack. Vẫn dùng được npm packages.

Transpile ES6 với Babel + bundle Webpack setup phức tạp. Rails support tốt với gem Webpacker nhưng mang theo nhiều baggage, khó hiểu, khó maintain upgradability.

Mặc định cho rails new giờ dùng import maps qua gem importmaps-rails. Thay vì package.json + npm/yarn, dùng ./bin/importmap CLI để pin/unpin/update dependencies.

Ví dụ cài date-fns:

$ ./bin/importmap pin date-fns

Thêm line vào config/importmap.rb:

pin "date-fns", to: "https://ga.jspm.io/npm:date-fns@2.27.0/esm/index.js"

JS code dùng như bình thường:

import { formatDistance, subDays } from "date-fns";
formatDistance(subDays(new Date(), 3), new Date(), { addSuffix: true }); //=> "3 days ago"

Lưu ý: Không transpile giữa code viết và browser nhận. OK vì browser hiện đại support ES6. Nhưng KHÔNG dùng được TypeScript hay JSX (cần transpile).

Muốn React với JSX? Fallback setup khác (webpack/rollup/esbuild). Rails 7 support:

$ ./bin/rails javascript:install:[esbuild|rollup|webpack]

Turbolinks & UJS → Turbo & Stimulus

Rails 7 mới sinh app mặc định dùng Turbo và Stimulus (từ Hotwire) thay Turbolinks và UJS. Hotwire: approach mới gửi HTML qua wire để update DOM nhanh.

Mã Hóa Ở Database Layer

Rails 7 cho phép mark fields encrypted dùng encrypts trên ActiveRecord::Base. Sau setup, code như sau:

class Message < ApplicationRecord
  encrypts :text
end

Dùng encrypted attributes như attributes bình thường. Rails 7 tự encrypt/decrypt giữa DB và app.

Quirk: Không query được field đó trừ khi pass deterministic: true cho encrypts. Deterministic mode kém an toàn hơn non-deterministic default, chỉ dùng cho attributes bắt buộc query.

Async Querying (Truy Vấn Bất Đồng Bộ)

Method load_async fetch results background. Quan trọng khi load nhiều queries unrelated từ controller action:

def PostsController
  def index
    @posts = Post.load_async
    @categories = Category.load_async
  end
end

Cả 2 query chạy background song song. Mỗi query 200ms → total ~200ms thay vì 400ms serial.

Zeitwerk Mode Cho Rails 7

Breaking change cho app cũ dùng classic loader. Tất cả Rails 7 apps phải dùng Zeitwerk mode. Switch dễ dàng. Xem Zeitwerk upgrade guide đầy đủ.

Các Cập Nhật Khác Của Rails 7

Retry Jobs Unlimited Times

ActiveJob cho phép :unlimited làm attempts param trên retry_on. Rails retry job không giới hạn lần.

class MyJob < ActiveJob::Base
  retry_on(AlwaysRetryException, attempts: :unlimited)
  def perform
    raise "KABOOM"
  end
end

Named Variants

Đặt tên variants trên ActiveStorage thay vì chỉ định size mỗi lần truy cập.

class User < ApplicationRecord
  has_one_attached :avatar do |attachable|
    attachable.variant :thumb, resize: "100x100"
  end
end
# Gọi avatar.variant(:thumb): <%= image_tag user.avatar.variant(:thumb) %>

Hash → HTML Attributes

Method mới tag.attributes cho views chuyển hash thành HTML attributes:

<input <%= tag.attributes(type: :text, aria: { label: "Search" }) %>>

Sinh ra:

<input type="text" aria-label="Search" />

Ruby debug

Default debugger thay byebug bằng gem debug. Gọi debugger thay vì byebug để vào debug session.

Assert Single Record Với sole

Query records, dùng sole hoặc find_sole_by (thay first/find_by) khi assert query chỉ match 1 record.

Product.where(["price = %?", price]).sole
# => ActiveRecord::RecordNotFound (nếu không có)
# => #<Product ...> (nếu có 1)
# => ActiveRecord::SoleRecordExceeded (nếu >1)
user.api_keys.find_sole_by(key: key) # tương tự

Check Presence/Absence Association

Dùng where.associated(:association) check association present thay vì join + check id existence.

# Before: account.users.joins(:contact).where.not(contact_id: nil)
# After:  account.users.where.associated(:contact)

Stream Generated Files Từ Controller Actions

Dùng send_stream trong controller action stream file đang generate on-the-fly:

send_stream(filename: "subscribers.csv") do |stream|
  stream.write "email_address,updated_at\n"
  @subscribers.find_each do |subscriber|
    stream.write "#{subscriber.email_address},#{subscriber.updated_at}\n"
  end
end

Response tức thì (partial) → user biết đang xử lý. Lợi ích deploy Heroku: không terminate connection (30s timeout), không cần background jobs cho file one-off >30s.

Nâng Cấp Lên Rails 7

Giống các version trước, upgrade đơn giản. Chưa có official guide nhưng steps giống nhau:

  1. Đổi Rails version trong Gemfile (7.0.0.rc1 lúc viết) → bundle update
  2. Chạy bundle exec rails app:update. Follow interactive CLI, add/replace/modify files.
  3. Chạy tests, verify mọi thứ works.

Kết Luận

Full list bug fixes, features, changes: Rails 7 release notes. Chưa comprehensive, sẽ update sớm.

Vẫn chạy Rails 6 hoặc thấp hơn? Lưu ý: Rails 7 final release → Rails 6.1 vào mode "security issues only", không còn bug fixes. Rails 5.2 EOL, không còn fixes.

Happy coding!

P.S. Đăng ký Ruby Magic newsletter để đọc sớm nhất!