each - find_each - find_in_batches - nil? - blank? - empty? - present? in rails

Giới thiệu:

khi chúng ta muốn thao tác với một số lượng lớn các bản ghi ví dụ như gửi mail cho nhiều user, hoặc update thông tin của nhiều user... chúng ta đều sử dụng vòng lặp để thực hiện. Trong rails có rất nhiều phương thức để thực hiện điều đó như:

  • each
  • find_each
  • find_in_batches

nhưng không phải cách nào cũng tốt và hiệu quả. để hiểu rõ hơn về điều đó, thì chúng ta đi vào tìm hiểu sự khác biệt giữa các phương thức đó.

each:

Candidate.all.each do |candidate|
  candidate // do something
end

có lẽ cách tiếp cận này là rất tồi, khi số lượng bản ghi lớn thì nó sẽ cố gắng khởi tạo ra tất cả các object và lưu trữ tất cả chúng trong bộ nhớ. Nếu số lượng bản ghi đủ lớn có thể vượt quá dung lượng bộ nhớ có thể cung cấp thì sẽ xảy ra việc tràn bộ nhớ. để có thể hạn chế được điều đó thì chúng ta có thể sử dụng với batch processing (find_each, find_in_batches), nó cho phép người dùng làm việc với một số lượng lớn các bản ghi rất thân thiện với bộ nhớ, giúp giảm dung lượng bộ nhớ cần sử dụng.

find_each:

Candidate.all.find_each do |candidate|
  candidate // do something
end

cách tiếp cận này có vẻ tốt hơn so với phương thức each, nhưng với find_each thì nó sẽ lấy ra các records theo từng batch sau đó gọi tới từng record trong khối như là một đối tượng riêng. Quá trình này được lặp đi lặp lại cho tới khi tất cả các record được xử lý xong.

find_in_batches:

Candidate.all.find_in_batches do |candidate|
  candidate // do something
end

cách này tương tự như find_each khi cũng lấy ra batch các records. Nhưng điểm khác biệt ở đây là gọi tới các batches đưa vào trong block dưới dạng một mảng các record thay vì đưa lần lượt từng record vào, điều đó cho thấy việc sửa dụng find_in_batches có lẽ là hiệu quả nhất trong việc thao tác với một số lượng lớn các bản ghi. ngoài việc lựa chọn phương thức phù hợp để thao tác với số lượng lớn các bản ghi thì việc nên lựa chọn phương thức nào để xác định true/false cho một chuỗi, một mảng, giá trị hay là một đối tượng thì cũng có sự tranh luận và thắc mắc rất nhiều giữa việc nên sử dụng nil? hay empty?, blank? hay là present? là phù hợp nhất, thì sau đây chúng ta đi vào phân tích từng phương thức một. trước hết như chúng ta biết thì nil? và empty? là hàm của ruby còn blank? và present? là của rails.

nil?

là một phương thức của Object, nên tất cả các object kế thừa từ Object mặc định đều có hàm nil?, chỉ có nil object trả về true khi gọi nil?

nil.nil?
 => true
"".nil?
=> false
90.nil?
 => false
Object.new.nil?
=> false

empty?

là function có sẵn của String, Array, Hash. Sẽ trả về là true nếu:

String length == 0 Array length == 0 Hash length == 0

"".empty?
=> true
[].empty?
=> true
{}.empty?
 => true
" ".empty?
=> false
[nil].empty?
=> false

blank?

là một hàm rất thú vị của Rails, cũng như được sử dụng rất thường xuyên cùng với present?, một object được coi là blank nếu như nó false hoặc là 1 chuỗi chỉ gồm các khoảng trắng

[].blank? 
=> true
{}.blank? 
=> true
"".blank? 
=> true
false.blank? 
=> true
nil.blank? 
=> true
"   ".blank? 
=> true

present?

present? ngược lại với blank?

"".present? 
=> false
"hoa".present? 
=> true

từ nhưng phân tích trên ta có thể tổng hợp lại như sau:

method/object nil? empty? blank? present?
nil True True false
false false True false
True false false True
"" false True True false
" " false false True false
0 false false True
[] false true True false
[nil] false false false True
{} false True True false
{a: nil} false false false True

Kết luận

Việc hiểu bản chất của các phương thức each, find_each, find_in_batches, nil?, empty?, blank? và present? cho phép các bạn thấy được sự khác nhau, cũng như hoàn cảnh mà các bạn nên áp dụng từng phương thức nào cho riêng mình. Hy vọng bài viết sẽ giúp ích cho các bạn!


All Rights Reserved