Khi lập trình web ắt hẳn các bạn sẽ dùng đến một trường ‘status’ (trạng thái). Nhưng với một trường là status thì làm sao để có thể lưu được nhiều trạng thái khác nhau, chắc sẽ có bạn sẽ nghĩ tới trường hợp sử dụng kiểu dữ liệu là boolean, nhưng với kiểu dữ liệu là boolean chúng ta chỉ có thể lưu trữ 2 loại trạng thái đó là true
hoặc false
, với lại cảm giác nó cũng không rõ ràng lắm nhỉ. Ví dụ bạn muốn nhiều hơn 2 trạng thái ví dụ như [:pending, :accept, :reject]
chả hạn. Thì ở bài viết lần này mình xin giới thiệu với các bạn một kĩ thuật trong rails để có thể xử lý tình huống này đó chính là Enum
.
Để sử dụng Enum
thì bạn cần khai báo kiểu dữ liệu ở đây là integer
thay vì kiểu dữ liệu boolean
hay string
. Enum cho phép bạn map các giá trị strings với các giá trị integer. Để khai báo dùng Enum
rất đơn giản bạn chỉ cần viết đoạn code sau trong model.
1 2 3 4 | <span class="token keyword">class</span> <span class="token class-name">Order</span> <span class="token operator"><</span> <span class="token constant">ApplicationRecord</span> enum status<span class="token punctuation">:</span> <span class="token punctuation">[</span><span class="token symbol">:pending</span><span class="token punctuation">,</span> <span class="token symbol">:accept</span><span class="token punctuation">,</span> <span class="token symbol">:reject</span><span class="token punctuation">]</span> <span class="token keyword">end</span> |
Nhìn ví dụ trên ta có thể tóm tắt định nghĩa của Enum
là Enum
là một tập hợp các giá trị có thể có của một thuộc tính.
Để sử dụng Enum
, rất đơn giản chỉ cần gọi đến các giá trị mà bạn khai báo đối với thuộc tính bạn khai báo là Enum
. Bạn có thể truy cập Enum
bởi một đối tượng, mở console lên và test nhé.
Ví dụ :
1 2 3 4 5 6 7 8 9 10 11 | order <span class="token operator">=</span> <span class="token constant">Order</span><span class="token punctuation">.</span>first <span class="token operator">=</span><span class="token operator">></span> <span class="token comment">#<Order id: 1, status: "pending", created_at: "2020-03-17 09:07:05", updated_at: "2020-03-17 09:07:05", user_id: 2></span> <span class="token comment"># để kiểm tra trạng thái của order có phải đang pending không, ta làm như sau</span> order<span class="token punctuation">.</span>pending<span class="token operator">?</span> <span class="token operator">=</span><span class="token operator">></span> <span class="token keyword">true</span> order<span class="token punctuation">.</span>accept<span class="token operator">?</span> <span class="token operator">=</span><span class="token operator">></span> <span class="token keyword">false</span> order<span class="token punctuation">.</span>reject<span class="token operator">?</span> <span class="token operator">=</span><span class="token operator">></span> <span class="token keyword">false</span> |
Hay là bạn muốn lấy tất cả các record mà có status là pending
:
1 2 3 4 5 | <span class="token constant">Order</span><span class="token punctuation">.</span>pending <span class="token comment"># tương tự nếu muốn lấy các status khác</span> <span class="token constant">Order</span><span class="token punctuation">.</span>accept <span class="token constant">Order</span><span class="token punctuation">.</span>reject |
Bạn có thể lấy tất cả các giá trị của status bằng cách
1 2 3 | <span class="token constant">Order</span><span class="token punctuation">.</span>statuses <span class="token comment"># gọi đến số nhiều của trường bạn đặt tên.</span> <span class="token operator">=</span><span class="token operator">></span> <span class="token punctuation">{</span><span class="token string">"pending"</span><span class="token operator">=</span><span class="token operator">></span><span class="token number">0</span><span class="token punctuation">,</span> <span class="token string">"accept"</span><span class="token operator">=</span><span class="token operator">></span><span class="token number">1</span><span class="token punctuation">,</span> <span class="token string">"refuse"</span><span class="token operator">=</span><span class="token operator">></span><span class="token number">2</span><span class="token punctuation">}</span> |
mặc định rails sẽ lưu các giá trị của enum lần lượt từ 0 trở lên. Bạn có thể đặt lại các giá trị đó bằng cách khai báo
1 2 3 4 5 6 7 | <span class="token keyword">class</span> <span class="token class-name">Conversation</span> <span class="token operator"><</span> <span class="token constant">ActiveRecord</span><span class="token punctuation">:</span><span class="token punctuation">:</span><span class="token constant">Base</span> enum status<span class="token punctuation">:</span> <span class="token punctuation">{</span> active<span class="token punctuation">:</span> <span class="token string">"a"</span><span class="token punctuation">,</span> archived<span class="token punctuation">:</span> <span class="token string">"b"</span> <span class="token punctuation">}</span> <span class="token keyword">end</span> <span class="token constant">Conversation</span><span class="token punctuation">.</span>statuses <span class="token operator">=</span><span class="token operator">></span> <span class="token punctuation">{</span><span class="token string">"active"</span><span class="token operator">=</span><span class="token operator">></span> <span class="token string">"a"</span><span class="token punctuation">,</span> <span class="token string">"archived"</span><span class="token operator">=</span><span class="token operator">></span> <span class="token string">"b"</span><span class="token punctuation">}</span> |
Sử dụng prefix và suffix trong enum
Nếu bạn không muốn gọi đến các giá trị của Enum
theo mặc định, mà thay vào đó muốn thêm các tiền tộ hậu tố khác đứng trước cái giá trị đó cho tường minh thì trong Rails chúng ta rất dễ dàng khai báo như sau. Ví dụ với suffix
:
1 2 3 4 | <span class="token keyword">class</span> <span class="token class-name">RegisterCourse</span> <span class="token operator"><</span> <span class="token constant">ApplicationRecord</span> enum status<span class="token punctuation">:</span> <span class="token punctuation">{</span>pending<span class="token punctuation">:</span> <span class="token number">0</span><span class="token punctuation">,</span> approve<span class="token punctuation">:</span> <span class="token number">1</span><span class="token punctuation">,</span> discard<span class="token punctuation">:</span> <span class="token number">2</span><span class="token punctuation">,</span> block<span class="token punctuation">:</span> <span class="token number">3</span><span class="token punctuation">}</span><span class="token punctuation">,</span> _suffix<span class="token punctuation">:</span> <span class="token keyword">true</span> <span class="token keyword">end</span> |
bình thường để lấy ra các record có trạng thái là pending
ta chỉ cần RegisterCourse.pending
. Thế nhưng nếu ta khai báo như thế kia và cố tình truy cập sẽ dẫn đến một thông báo lỗi :
1 2 | <span class="token constant">NoMethodError</span> <span class="token punctuation">(</span>undefined method `pending' <span class="token keyword">for</span> <span class="token comment">#<Class:0x00007f1f9977f5f0>)</span> |
Vì có khai báo _suffix: true
nên để gọi đến nó ta phải gọi như sau
1 2 3 | <span class="token constant">RegisterCourse</span><span class="token punctuation">.</span>pending_status |
Mặc định rails sẽ lấy hậu tố là tên trường, ở trong trường hợp này nó là status
.
Nếu không muốn sẽ dụng theo mặc định ta có thể khai báo và đặt một tên khác như sau:
1 2 3 4 5 6 7 | <span class="token keyword">class</span> <span class="token class-name">RegisterCourse</span> <span class="token operator"><</span> <span class="token constant">ApplicationRecord</span> enum status<span class="token punctuation">:</span> <span class="token punctuation">{</span>pending<span class="token punctuation">:</span> <span class="token number">0</span><span class="token punctuation">,</span> approve<span class="token punctuation">:</span> <span class="token number">1</span><span class="token punctuation">,</span> discard<span class="token punctuation">:</span> <span class="token number">2</span><span class="token punctuation">,</span> block<span class="token punctuation">:</span> <span class="token number">3</span><span class="token punctuation">}</span><span class="token punctuation">,</span> _suffix<span class="token punctuation">:</span> <span class="token string">"hello"</span> <span class="token keyword">end</span> <span class="token comment"># để truy cập</span> <span class="token constant">RegisterCourse</span><span class="token punctuation">.</span>pending_hello |
Tương tự ta sử dụng nó với prefix
1 2 3 4 5 6 7 | <span class="token keyword">class</span> <span class="token class-name">RegisterCourse</span> <span class="token operator"><</span> <span class="token constant">ApplicationRecord</span> enum status<span class="token punctuation">:</span> <span class="token punctuation">{</span>pending<span class="token punctuation">:</span> <span class="token number">0</span><span class="token punctuation">,</span> approve<span class="token punctuation">:</span> <span class="token number">1</span><span class="token punctuation">,</span> discard<span class="token punctuation">:</span> <span class="token number">2</span><span class="token punctuation">,</span> block<span class="token punctuation">:</span> <span class="token number">3</span><span class="token punctuation">}</span><span class="token punctuation">,</span> _prefix<span class="token punctuation">:</span> <span class="token keyword">true</span> <span class="token keyword">end</span> <span class="token comment"># để truy cập </span> <span class="token constant">RegisterCourse</span><span class="token punctuation">.</span>status_pending |
hay đặt một cái tên tiền tố khác
1 2 3 4 5 6 7 | <span class="token keyword">class</span> <span class="token class-name">RegisterCourse</span> <span class="token operator"><</span> <span class="token constant">ApplicationRecord</span> enum status<span class="token punctuation">:</span> <span class="token punctuation">{</span>pending<span class="token punctuation">:</span> <span class="token number">0</span><span class="token punctuation">,</span> approve<span class="token punctuation">:</span> <span class="token number">1</span><span class="token punctuation">,</span> discard<span class="token punctuation">:</span> <span class="token number">2</span><span class="token punctuation">,</span> block<span class="token punctuation">:</span> <span class="token number">3</span><span class="token punctuation">}</span><span class="token punctuation">,</span> _prefix<span class="token punctuation">:</span> <span class="token string">"hello"</span> <span class="token keyword">end</span> <span class="token comment"># để truy cập</span> <span class="token constant">RegisterCourse</span><span class="token punctuation">.</span>hello_pending |
Như vậy đó là những gì mà mình muốn giới thiệu với các bạn trong bài viết lần này.
Tài liệu tham khảo https://api.rubyonrails.org/v5.2.4.1/classes/ActiveRecord/Enum.html