Kredis (Keyed Redis) là một bổ sung gần đây vào bộ công cụ của nhà phát triển Rails. Nó nỗ lực đơn giản hóa việc lưu trữ và truy cập dữ liệu có cấu trúc trên Redis.
Trong phần đầu tiên của loạt bài hai phần này, chúng ta sẽ bắt đầu bằng cách đi sâu vào cách Kredis hoạt động. Sau đó chúng ta sẽ chạy qua một trường hợp sử dụng ví dụ để lưu trữ trạng thái UI thời vụ (ephemeral UI state) bằng một khóa Redis tùy chỉnh.
Hãy bắt đầu!
Giới Thiệu Kredis Cho Rails
Kredis là một Railtie cung cấp các wrapper tiện lợi để hợp lý hóa việc sử dụng nó theo ba cách:
- API kiểu Ruby (Ruby-esque API): Ví dụ, các kiểu collection như
Kredis.listhoặcKredis.setmô phỏng các kiểu Ruby native (và API tương ứng của chúng) nhiều nhất có thể. - Typings (Kiểu dữ liệu): Đặc biệt thuận tiện cho collections, Kredis có thể xử lý type casting (chuyển đổi kiểu) các phần tử từ/đến các kiểu dữ liệu chuẩn (ví dụ:
datetime,json). - ActiveRecord DSL: Có lẽ là tài sản lớn nhất của thư viện, nó cho phép bạn dễ dàng kết nối bất kỳ cấu trúc dữ liệu Redis nào với một instance model cụ thể.
Đây là ví dụ từ README:
Lợi ích chính của Kredis là sự dễ dàng nó cung cấp để lưu trữ thông tin thời vụ liên quan đến một bản ghi nhất định, nhưng độc lập với session. Thông thường, khi bạn cần lưu dữ liệu trong Rails, bạn có một vài lựa chọn — trong đó hai phổ biến nhất là:
- ActiveRecord: Trong hầu hết trường hợp, điều này đòi hỏi thêm cột hoặc sửa đổi model dữ liệu. Cần migration, cộng với việc backfill (điền dữ liệu ngược) cho bản ghi cũ (tùy chọn).
- Session: Kho key/value mặc định của mọi ứng dụng Rails và yêu cầu thiết lập không hoặc rất ít. Nhược điểm là dữ liệu lưu trong nó không sống sót qua chu kỳ login/logout.
Kredis mang đến một lựa chọn thứ ba. Thiết lập rất ít, ngoài việc gọi DSL trong model. Nhưng trừ khi instance Redis của bạn sập, dữ liệu của bạn được lưu trữ qua các session, thậm chí cả thiết bị. Vì vậy, trường hợp sử dụng tốt cho Kredis là thông tin không quan trọng mà bạn muốn chia sẻ qua ranh giới thiết bị, ví dụ trong web app và mobile app đi kèm.
Case Study: Duy Trì & Khôi Phục Trạng Thái Thu Gọn/Mở Rộng UI Sử Dụng Kredis
Một trường hợp điển hình của use case tốt cho Kredis là khi lưu trữ trạng thái UI, chẳng hạn như:
- Trạng thái mở/đóng sidebar
- Trạng thái mở/đóng tree view
- Trạng thái thu gọn/mở rộng accordion
- Layout dashboard tùy chỉnh
- Số dòng hiển thị của bảng dữ liệu
Ví dụ minh họa, chúng ta sẽ xem cách quản lý trạng thái thu gọn/mở rộng của một phần tử <details>.
Hãy bắt đầu với một Rails app mới, thêm kredis vào bundle, và chạy installer của nó:
Lưu ý: Điều này sẽ tạo file cấu hình Redis trong config/redis/shared.yml.
Trong phần còn lại của bài viết, tôi sẽ giả định bạn có instance Redis cục bộ đang chạy. Trên macOS với Homebrew, việc này dễ dàng như chạy:
Vui lòng tham khảo hướng dẫn "Getting Started" chính thức để biết cách cài đặt Redis trên hệ điều hành của bạn.
Xác Thực Người Dùng
Chúng ta sẽ dùng model User làm thực thể để lưu thông tin trạng thái UI. Để tránh tranh luận vô ích (bikeshedding), hãy dùng những gì Devise cung cấp sẵn:
Chúng ta tạo user ví dụ trong Rails console:
Ứng Dụng Ví Dụ: Cửa Hàng Trực Tuyến
Để minh họa cách Kredis giúp lưu trạng thái của cấu trúc cây phức tạp, hãy giả vờ chúng ta đang điều hành một cửa hàng bộ phận trực tuyến. Đến đó, chúng ta sẽ scaffold model Department và Product. Chúng ta bao gồm self-join từ department đến department, để tạo cấu trúc lồng nhau hai cấp:
Chúng ta phải cho phép parent null, tất nhiên, để cho phép root của cây:
Model Department và Product được định nghĩa như sau:
Cuối cùng, chúng ta dùng faker để tạo dữ liệu seed:
Scaffold Storefront (Mặt Tiền Cửa Hàng)
Chúng ta sẽ tạo một HomeController rất đơn giản đóng vai trò mặt tiền cửa hàng.
Chúng ta thực hiện self join trên children của departments để chỉ lấy những department thực sự có sub-department (hay nói cách khác, là root của cây):
Trong view index, chúng ta thiết lập nested tree view sử dụng hai cấp <details> cho departments:
Lúc này chúng ta có tree view các department với tên sản phẩm cố tình hài hước mà chúng ta có thể khám phá bằng cách mở và đóng:

Chúng ta muốn lưu trữ trạng thái disclosure (mở/đóng) của các category riêng lẻ, điều này chúng ta sẽ giải quyết ngay.
Lưu Trữ Trạng Thái UI Của Category Trong Kredis
Đây là những gì chúng ta sẽ làm, từng bước:
-
Thêm một
kredis_settênopen_department_idsvào modelUser. Lý do dùng set ở đây là nó không cho phép trùng lặp, nên chúng ta có thể an toàn thêm và xóa department. -
Tạo một
UIStateControllernhận các param sau:department_id- trạng thái
opencủa department đó
Nó sẽ thêm hoặc xóa department này vào
kredis_setcho user đang đăng nhập. -
Tạo một Stimulus controller sẽ lắng nghe sự kiện toggle trên phần tử details và gửi payload tương ứng.
Hãy bắt đầu!
Thêm cấu trúc dữ liệu Kredis nói trên vào model User dễ dàng như gọi kredis_set và truyền một identifier:
Tiếp theo, chúng ta generate UIStateController để nhận cập nhật trạng thái UI. Lưu ý chúng ta phải cấu hình route được generate thành endpoint patch:
Cuộc gặp đầu tiên với API của Kredis là ở controller. Chúng ta thấy nó cố gắng tuân theo kỳ vọng của nhà phát triển Ruby càng gần càng tốt, nên bạn có thể thêm vào set dùng <<, và xóa dùng remove.
Điều xảy ra ở đây là chúng ta toggle sự hiện diện của một department_id cụ thể trong set dựa trên param open được chuyển từ client. Để hoàn thiện bức tranh, chúng ta phải viết mã client-side để truyền các thay đổi trạng thái UI này.
Chúng ta sẽ dùng @rails/request.js để thực hiện hành động, nên phải pin nó:
Trong một Stimulus controller mới mà chúng ta sẽ gắn vào một phần tử <details> cụ thể, chúng ta thêm department ID và trạng thái open vào đối tượng FormData, và submit nó:
Chúng ta sửa mã view như đề xuất, và lắng nghe sự kiện toggle của mỗi phần tử <details> để kích hoạt cập nhật trạng thái UI:
Rehydrate (Khôi Phục) DOM Thủ Công
Thành phần còn thiếu để hoàn thành vòng tròn là rehydrating DOM về trạng thái mong muốn khi người dùng refresh trang. Chúng ta làm thủ công bằng cách thêm thuộc tính open vào node <details> (nếu department ID của nó có trong Kredis set):
Cuối cùng, đây là kết quả. Lưu ý trạng thái mở/đóng của các node cây riêng lẻ được bảo toàn qua 2 cấp:
Tiếp Theo: Container Cục Bộ Người Dùng Tổng Quát Cho Trạng Thái UI
Trong phần đầu tiên của loạt bài hai phần này, chúng ta giới thiệu Kredis và khám phá cách lưu trữ và khôi phục trạng thái thu gọn/mở rộng UI với Kredis.
Chúng ta dùng ví dụ cửa hàng bộ phận trực tuyến để làm nổi bật cách Kredis có thể lưu trạng thái của cấu trúc cây phức tạp, trước khi khôi phục DOM thủ công.
Tuy nhiên, điều này có nghĩa là chúng ta phải phát minh ra nhiều khóa Kredis. Lần sau, chúng ta sẽ đi sâu vào cách giải quyết vấn đề này với một container cục bộ người dùng tổng quát cho trạng thái UI.
Cho đến lúc đó, chúc bạn viết mã vui vẻ!
P.S. Nếu bạn muốn đọc các bài Ruby Magic ngay khi chúng xuất bản, hãy đăng ký bản tin Ruby Magic của chúng tôi và không bao giờ bỏ lỡ bất kỳ bài viết nào!