Last Updated: February 25, 2016
·
1.671K
· yeuem1vannam

10 methods hữu dụng trong ActiveRecord::Relation

Dưới đây là 10 methods hữu dụng nhất trong ActiveRecord::Relation

1. merge

Đây là 1 method rất hữu dụng khi sử dụng trong ActiveRecord::Relation. Bạn có thể vừa joins bảng vừa lọc với 1 scope nào đó trong models

class Account < ActiveRecord::Base
  # ...
  # Returns all the accounts that have unread messages.
  def self.with_unread_messages
    joins(:messages).merge( Message.unread )
  end
end

2. pluck

Khi muốn đưa ra array giá trị 1 cột của các records, thông thường ta hay sử dụng

published_book_titles = Book.published.select(:title).map(&:title)

hay là

published_book_titles = Book.published.map(&:title)

thì ta có thể dùng pluck để thay thế

published_book_titles = Book.published.pluck(:title)

3. scoping

Bạn có thể viết lại 1 class method riêng cho 1 trường hợp nào đó giống như scope với models. Tham khảo ví dụ dưới đây được lấy từ tài liệu của Rails

 Comment.where(:post_id => 1).scoping do
  Comment.first # SELECT * FROM comments WHERE post_id = 1
end

4. find_by

Trong Rails 4, method find_by_xxx không còn được sử dụng nên bạn thường dùng

Book.where(:title => ‘Three Day Road’, :author => ‘Joseph Boyden’).first

nhưng bạn có thể thay thế hoàn toàn bằng cách dùng find_by

Book.find_by(:title => ‘Three Day Road’, :author => ‘Joseph Boyden’)

5. to_sqlexplain

Trong khi sử dụng ActiveRecord, những methods của nó có thể không thực hiện những query giống như bạn nghĩ. Vì thế nên kiểm tra lại nó bằng to_sqlexplain để có thể chắc chắn rằng query của bạn là 1 query tốt, hoặc chỉ đơn giản là cho bạn thấy sự khác biệt giữa cách bạn viết và thứ bạn nghĩ

Library.joins(:book).to_sql
# => SQL query for you database.

Libray.joins(:book).explain
# => Database explain for the query.

6. find_each

Khi bạn muốn thực hiện 1 update cho hàng ngàn records, không nên sử dụng each bởi vì:

  • ActiveRecord sẽ thực hiện 1 query lấy ra toàn bộ records
  • Đưa toàn bộ số records vào memory
  • Thực hiện update cho toàn bộ số records cùng lúc

Nếu memory của bạn đủ lớn, thì điều này không những không vấn đề gì, mà còn tăng hiệu năng của hệ thống, nhưng ngược lại, nó sẽ là nguyên nhân chính khiến cho hệ thống của bạn bị chậm, hay thậm chí là ngưng hoạt động.
Với find_each, nó sẽ thực hiện update cho từng record một, và hệ thống sẽ không phải lưu trữ toàn bộ records trong cùng 1 khoảng thời gian

Book.where(:published => true).find_each do |book|
  puts “Do something with #{book.title} here!”
end

7. none (Rails4 only)

Khi ActiveRecord không trả về kết quả nào, điều này rất không tốt nếu như API của bạn mong muốn đầu vào là 1 ActiveRecord::Relation. Trong trường hợp này bạn có thể sự dụng none

def filter(filter_name)
  case filter_name
  when :all
    scoped
  when :published
    where(:published => true)
  when :unpublished
    where(:published => false)
  else
    none
  end
end

8. scoped

Ngược lại với phần trên, khi bạn muốn ActiveRecord::Relation trả về toàn bộ records của class, có thể dùng scoped

def search(query)
  if query.blank?
    scoped
  else
    q = "%#{query}%"
    where("title like ? or author like ?", q, q)
  end
end

9. first_or_initialize

Muốn lấy ra record nào đó, nếu nó không tồn tại thì tạo mới nó? Sử dụng first_or_initialize

Book.where(:title => 'Tale of Two Cities').first_or_initialize

10. first_or_create with a block

Tương tự như first_or_initialize nhưng bạn muốn tạo mới 1 record và save luôn vào database thì có thể dùng first_or_create

Book.where(:title => 'Tale of Two Cities').first_or_create

Reference

http://blog.mitchcrowe.com/