Enum Và Sự Khác Biệt Khi Sử Dụng Giữa Rails 4.x Và Rails 5.x - Code24h

  • Bài viết
  • Hỏi đáp
Tạo bài viết Đăng ký Đăng nhập Code24h.com Blog 12/08/2018, 14:52 Enum và sự khác biệt khi sử dụng giữa rails 4.x và rails 5.x

Có thể nói nôm na: Enum là trường được định nghĩa là enum thì sẽ lưu trong DB là số nhưng mà lại có thể được truy xuất bằng chữ Ví dụ : Model User có trường role: [:member, :admin] thì được lưu trong DB tương ứng là 0, 1 nhưng có thể được truy xuất bằng chữ : User.member, User.admin Cú pháp: ...

  • Có thể nói nôm na: Enum là trường được định nghĩa là enum thì sẽ lưu trong DB là số nhưng mà lại có thể được truy xuất bằng chữ
  • Ví dụ : Model User có trường role: [:member, :admin] thì được lưu trong DB tương ứng là 0, 1 nhưng có thể được truy xuất bằng chữ : User.member, User.admin
  • Cú pháp:
class User < ActiveRecord::Base enum role: [:member, :admin] end
  • Nếu trường dùng làm enum nhận giá trị nil và mọi hàm gán cho giá trị này đều trả về False

  • Vì vậy: Trường lưu trữ enum nên để nullable: false và có giá trị mặc định(default):

class CreateUsers < ActiveRecord::Migration[5.0] def change create_table :users do |t| t.integer :role, null: false, default: 0 t.timestamps end end end
  • Như ta thấy : Ứng với các function admin, member là các scope, nên chúng ta có thể nối thêm các scope khác để truy xuất thuận tiện hơn. Thay vì viết:
User.where(role: 0)

Thì ta viết:

User.admin

sẽ trực quan và ý nghĩa hơn nhiều. Bên cạnh đó có thể nối thêm các scope hay mệnh đề khác:

User.admin.where(id: 1)
  • Đến đây vẫn chưa thấy được sự khác biệt của enum trong rails 4 và rails 5, phần tiếp theo mình xin trình bày sự khác biệt đó. Thử một ví dụ trước nhé để xem sự khác biệt đó.: Ở rails 4:

  • Như chúng ta thấy, cả 2 trường hợp đều cho kết quả không mong muốn, vì bản chất role được lưu vào DB là số, nên khi sử dụng mệnh đề where thì nó convert về dạng int: +) "member".to_i = 0 nên thành ra nó tìm các bản ghi có role là 0 (ứng với admin). +) :member là symbol không có hàm to_i nên nó so sánh role với nil. *Vì vậy lưu ý cho mình : Với rails 4 tuyệt đối không so sánh các trường enum với string hoặc symbol. Còn với rails 5:

  • Như chúng ta thấy, vẫn với câu lệnh như bên kia nhưng kết quả trả về khác hẳn, đúng như những kết quả ta mong muốn. Đây cũng chính là điểm khác biệt mình muốn đề cập tới, những cái gọi là còn "tồn đọng", "khuyết điểm" ở rails 4 tới đây đã được giải quyết.

  • Còn 1 điều khá là nguy hiểm nên mình tách riêng ra ở đây: Vì bản chất rails 4 convert giá trị so sánh về dạng integer trước khi đem so sánh nên sẽ có thể xảy ra trường hợp sau:

  • Rõ ràng là không có thằng nào có role : "adminnn" và cũng không tồn tại "adminnn" trong enum nhưng vẫn select ra được, do "adminnn".to_i = 0.

  • Với rails 5 thì kết quả khác hẳn:

  • Vẫn với lý do như trên bản chất rails 4 convert cái mình truyền vào thành integer sau đó so sánh với 0,1,... Còn rails 5 đã update có cơ chế convert ngược nên không còn xảy ra tình trạng trên.

  • Thêm vào ngoài cùng bên phía tay phải
class User < ApplicationRecord enum role: [:admin, :member, :mod] end
  • Khi đó theo logic lưu vào DB: mod ứng với 2, và role các bản ghi trước đó không bị ảnh hưởng. Nhưng giả sử mình thêm :mod vào ngoài cùng tay trái.
class User < ApplicationRecord enum role: [:mod, :admin, :member] end
  • Khi đó :admin từ 0 thành 1, :member từ 1 thành 2 và các bản ghi trước sẽ bị ảnh hưởng
  • Vậy câu hỏi đặt ra là : "Tôi muốn đặt "mod" ở đầu tiên mà không làm ảnh hưởng tới các bản ghi trước có được không? "
  • Câu trả lời là được vì rails hỗ trợ xét giá trị role theo kiểu Hash
class User < ApplicationRecord enum role: { mod: 2, admin: 0, member: 1} end
  • Và khi đó kết quả lại trở về như cũ và không bị ảnh hưởng gì
  • User đầu tiên lại trở về role như ban đầu là "member"
  1. Enum hỗ trợ lưu trữ trong DB là số nhưng có thể truy xuất qua chữ nên nó rất trực quan.
  2. Trường lưu trữ Enum không nên để nullable và luôn có giá trị mặc định
  3. Khi sử dụng rails 4 nên chú ý không được so sánh trực tiếp trường có kiểu enum với string hoặc symbol
  4. Các key của enum trong cùng 1 class không được trùng nhau và trùng với từ khóa
  5. Có thể biểu diễn enum dưới dạng Hash
  1. https://viblo.asia/ta.duy.anh/posts/nwmGyElDGoW
  2. http://api.rubyonrails.org/classes/ActiveRecord/Enum.html
Bình luận về bài viết này

Hoàng Hải Đăng

24 chủ đề

7226 bài viết

Có thể bạn quan tâm
  • 1 Một số phép nối bảng trong Mysql
  • 2 Chu trình kiểm thử phần mềm
  • 3 Nested Classes (P1)
  • 4 A simple API using protobuf and gRPC
  • 5 LLDB Debugger
  • 6 Kiểm thử phần mềm bắt đầu khi nào?
  • 7 Space Position pattern - Công nghệ chọn gấu
  • 8 Kiến trúc hệ thống trên Laravel – phần 4
  • 9 Building a Shopping Cart in Ruby on Rails
  • 10 Interface trong Typescript (Phần 1)
0 Các chủ đề đang được quan tâm phần mềm lập trình php | lập trình web php + mysql | khóa học lập trình php | tự học lập trình php | học php cơ bản thachpham | Code24h | Cho thuê phòng trọ hà nội | Cho thuê phòng trọ bình thạnh | Cho thuê phòng trọ | Cho thuê nhà trọ Đăng ký

Đăng ký nhận thông báo

Các bài học thú vị sẽ được gửi đến inbox của bạn

HỖ TRỢ HỌC VIÊN
  • Các câu hỏi thường gặp
  • Điều khoản sử dụng
  • Chính sách và quy định
  • Chính sách bảo mật thanh toán
  • Hỗ trợ học viên: hotro@code24h.com
  • Báo lỗi bảo mật: security@code24h.com
VỀ CODE24H
  • Giới thiệu Code24h
  • Cơ hội nghề nghiệp
  • Liên hệ với chúng tôi
HỢP TÁC VÀ LIÊN KẾT
  • Đăng ký giảng viên
  • Giải pháp e-learning
  • Chương trình đại lý
  • Chương trình Affiliate
KẾT NỐI VỚI CHÚNG TÔI
TẢI ỨNG DỤNG TRÊN ĐIỆN THOẠI

CCode 24h, code mọi lúc, mọi nơi

© Copy right 2018 - 2024

Từ khóa » Cú Pháp Trong Rails