Zeitwerk, Autoloading và Reloading trong Rails

Rails hiện đại dùng Zeitwerk để map tên constant với đường dẫn file. Ý tưởng cốt lõi: cấu trúc thư mục và namespace phải nói cùng một ngôn ngữ.

1
app/services/billing/invoice_creator.rb

phải định nghĩa:

1
2
3
4
module Billing
class InvoiceCreator
end
end

Nếu file tên một đằng, constant tên một nẻo, Rails không “đoán thông minh”; nó báo lỗi, và lần này Rails đúng.

Autoload paths

Các thư mục như app/models, app/controllers, app/jobs và custom directories dưới app thường nằm trong autoload paths. Không cần require file application theo cách thủ công.

Kiểm tra setup:

1
bin/rails zeitwerk:check

Command này nên chạy trong CI trước deploy.

Eager loading

Ở production, Rails thường eager load application code khi boot:

1
config.eager_load = true

Lợi ích:

  • phát hiện naming error khi boot thay vì request đầu tiên;
  • tránh autoload không thread-safe theo kiểu cổ điển;
  • phù hợp với copy-on-write khi preload trước khi fork worker.

Reloading trong development

Development reloader unload constant có thể reload rồi load lại code khi file thay đổi. Vì vậy không nên cache object class có thể reload trong global state lâu dài.

Code cần chạy lại sau mỗi reload đặt trong:

1
2
3
Rails.application.config.to_prepare do
# Decorator/patch cần idempotent
end

Block có thể chạy nhiều lần, nên code phải idempotent. “Chạy đúng lần đầu” không phải lifecycle contract.

require dùng khi nào?

Vẫn dùng require cho thư viện Ruby/gem không được Zeitwerk quản lý. Với code trong autoload paths, ưu tiên naming convention và constant reference.

Custom directory ngoài convention có thể cấu hình rõ ràng, nhưng đừng thêm mọi thư mục vào autoload_paths để lỗi biến mất. Đó là quét bụi xuống dưới carpet, chỉ khác là carpet biết Ruby.

Reference