2013-03-20 19 views
7

Tôi háo hức tải một đối tượng mô hình với các hiệp hội của nó:Rails tải Háo hức và mệnh đề where

user= User.includes(:posts).find(1) 

Nhưng sau đó tại một số điểm trong đoạn code tôi muốn làm một cái gì đó như thế này:

user.posts.where(:topic => "x") 

Nhưng điều đó chỉ chạy lại truy vấn một lần nữa. Vì vậy, thay vào đó tôi nghĩ tôi sẽ làm điều này:

user.posts.select{|post| post.topic == "x" } 

Điều đó không chạy lại truy vấn. Nhưng tôi có một vài câu hỏi.

Trước tiên, đây có phải là cách phù hợp để làm điều đó không?

Thứ hai, tôi hơi bối rối về lựa chọn trong trường hợp này. Bởi vì khi tôi chạy dòng cuối cùng ngay cả khi tôi đã không sử dụng chức năng bao gồm, lần đầu tiên nó chạy truy vấn và sau đó sau đó nếu tôi chạy nó một lần nữa, nó không .. như vậy là có một số loại bộ nhớ đệm có liên quan? Bởi vì khi tôi sử dụng mệnh đề where nó chạy truy vấn mỗi lần duy nhất.

Cảm ơn bạn.

Trả lời

14

select là phương pháp Ruby trên Số. Lần đầu tiên bạn chạy

user.posts.select{|post| post.topic == "x" } 

tất cả Post trường cho user 's :posts hiệp hội sẽ được nạp từ cơ sở dữ liệu vào bộ nhớ; cụ thể vào đối tượng bộ sưu tập ActiveRecord. select sau đó được gọi trên bộ sưu tập này, lọc ra tất cả các trường hợp Post trong bộ sưu tập có thuộc tính :topic là bất kỳ thông tin nào khác ngoài "x".

Chạy dòng trên một lần nữa sẽ không truy vấn lại cơ sở dữ liệu vì bạn đã tải posts vào bộ nhớ.


Khi bạn làm một includes như dưới đây

user= User.includes(:posts).find(1) 

nó sẽ tải háo hức quan hệ :posts cho mỗi User dụ trả lại (trong trường hợp này, một đơn User nơi :id1). Bây giờ bạn có tất cả các trường hợp Post được tải vào bộ nhớ như được mô tả trong phần trước ở trên.

Nếu bạn sau đó làm một cái gì đó giống như

user.posts.where(:topic => "x") 

bây giờ bạn đang nói với đường ray để chạy một truy vấn mới chống Post, lần này tìm tất cả Post trường hợp :topic"x" và nơi :user_id:id của user. where không hoạt động giống như "bộ lọc" trên bộ sưu tập AREL trong bộ nhớ.


  • Nếu bạn muốn tránh một truy vấn mà xấu, select là một cách tốt để lọc kết quả thiết lập trong bộ nhớ.
  • Bạn có thể chạy các tiêu chuẩn để tìm đó là nhanh hơn:
    1. truy vấn db và repopulating một bộ sưu tập Arel vào bộ nhớ
    2. iterating trên enumberable trong bộ nhớ và chạy một bộ lọc với Ruby
  • Nếu bạn không bao giờ cần tất cả liên quan :posts cho user, bạn có thể dễ dàng bao gồm điều này trong truy vấn ban đầu

    user.includes(:posts).where("posts.topic = ?", 'x') 
    
+0

Điều này là hoàn hảo, cảm ơn! – user1069624