Tương tự Ruby thì trong Rails cung cấp cho chúng ta nhiều cách để làm một hành động tương tự nhau. Ví dụ rõ ràng nhất là bài toán tìm số phần tử trong một Collection. Bạn có thể sử dụng các method length, size và count để thực hiện việc này.
Tuy nhiên, bạn cảm thấy khó hiểu vì sao lại có tận 3 method và chúng khác nhau như thế nào? Khi nào nên sử dụng chúng hoặc lựa chọn chúng có ảnh hưởng đến performance của dự án hay không? Bài đăng này sẽ khám phá sự khác biệt của chúng.
Hãy bắt đầu với cái nhìn tổng quan về các phương thức này trong Array của Ruby. Sau đó chúng ta sẽ chuyển sang Rails.
Ruby
1. Length
Đây là phương thức đơn giản nhất và thân thuộc nhất trong 3 loại. Bạn có thể thấy chúng trong bất kì dự án nào bạn làm.
Method length nó trả về số lượng phần tử trong một mảng.
Cú pháp rất đơn giản phải không nào?
numbers = [1,2,3,4,5,6]
numbers.length # => 6
2. Size
Size thực chất là alias của length. Cách nó thực thi giống như length vậy.
rubynumbers = [1,2,3,4,5,6]
numbers.size # => 6
Vậy thì khi nào sẽ sử dụng length và size? Đó là sử dụng tuỳ theo ngữ cảnh mà bạn đang gặp phải.
Ví dụ: Nếu tôi có một mảng class_room chứa một nhóm các học sinh, tôi sẽ sử dụng class_room.size thay vì class_room.length. Mặc khác, nếu tôi sử lý một mảng các numbers, tôi sẽ sử dụng method length
.
3. Count
Phương thức này thường được sử dụng để đếm số phần tử được chỉ định trong Array. Sử dụng chúng khi bạn cần tìm một phần tử phù hợp với một tiêu chí nào đó. Có 4 trường hợp sử dụng phương pháp này.
3.1 Nếu như không có argument và không có block, trả về số lượng tất cả các phần tử
[10, 20, 30].count # => 3
[].count # => 0
3.2 Khi có argument, trả về argument được cung cấp
[0, 5, 10, 0.0].count(0) # => 2
[0, 1, 2].count(3) # => 0
3.3 Khi có block nhưng lại không có argument
[0, 5, 10, 15].count { |e| e > 5 } # => 2
3.4 Nếu vừa có cả block và argument, nó bỏ qua block và trả về các đối số thoả điều kiện
[0, 1, 2, 3].count(2) { |e| e = 0 } # => 1
Nhưng phương thức này sẽ trả ra một WARNING như bên dưới:
Ruby On Rails
Chúng ta sẽ lấy ví dụ từ lớp ActiveRecord::Associations::CollectionProxy được kế thừa từ lớp ActiveRecord::Relation.
class Company < ActiveRecord::Base
has_many :company_members
end
company = Company.first
company_members = company.company_members
# CompanyMember::ActiveRecord_Associations_CollectionProxy
company_members.class
Ở ví dụ trên, comments là một Collection Proxy, bây giờ hãy tìm hiểu cách các phương thức này hoạt động trên Collection Proxy.
1. Size
Nếu collection chưa được query, thì phương thức size sẽ thực thi câu lệnh SELECT COUNT(*). Ngược lại thì chúng sẽ gọi collection.size
Company.all.size
# SELECT "companies".* FROM "companies"
2. Length
Trả về size cua Collection bằng cách call method size.
Company.all.length
# SELECT "companies".* FROM "companies"
Điều đó có nghĩa thì nếu collection đã được loaded thì method size và length tương đương nhau
Vậy khi nào nên dùng size
vs length
?
Khi Collection đã được loaded thì method size và length đều như nhau.
Còn nếu collection không được load từ database:
- Nếu bạn cần vẫn cần records bất cứ lúc nào thì hãy sử dụng method length. Điều này sẽ giảm đi một truy vấn, vì Rails sẽ sử dụng các bản ghi được lưu trong bộ nhớ cache cho truy vấn sau đó.
- Nếu bạn không cần records thì sử dụng method size sẽ hiệu quả hơn. Method này sẽ thực hiện một truy vấn COUNT SQL để lấy số lượng trực tiếp từ cơ sở dữ liệu, mà không cần tải các bản ghi vào bộ nhớ.
3. Count
Tương tự như method count của Ruby, method count trong Rails đếm tất cả các bản ghi trong một tập hợp thỏa mãn một điều kiện cho trước. Có 2 trường hợp sử dụng:
- Khi không có block, trả về số lượng tất cả records trong table
companies = Company.all
# SELECT COUNT(*) FROM "companies"
companies.count
- Khi có block, method count trong Rails gọi block với mỗi phần tử trong tập hợp và trả về số lượng phần tử mà khối trả về giá trị đúng (truthy).
Company.all.count { |company| company.charge_firstname.include?('Be') }
KẾT
Hy vọng rằng bạn đã thấy bài viết này hữu ích và bạn đã học được điều gì đó mới. 😀