2012-12-03 28 views
6

Tôi có một trang chủ có một số partials được hiển thị trên tất cả các trang. Và nó cũng có tiêu đề phiên cũng (đăng nhập). Một phần chứa bộ sách được phân trang. Bây giờ tôi muốn cache phần này vì nó đang được cập nhật một lần trong một tuần.Caching đường ray một phần cụ thể 3.0.x

  • Câu hỏi 1: Làm cách nào để lưu bộ nhớ cache một phần cụ thể (Không nhấn db)?
  • Câu hỏi 2: Làm cách nào để xóa (hết hạn) nội dung được lưu trong bộ nhớ cache khi tôi cập nhật sách đó có mô hình?

Trả lời

8

Bạn đang tìm kiếm fragment caching tại đây, xuất hiện trên lớp chế độ xem. Việc lưu trữ bộ nhớ đệm và hết hạn nội dung được lưu trữ thật đáng ngạc nhiên. Bạn có một danh sách các cuốn sách, vì vậy chúng ta hãy nói xem bạn trông hơi như thế này:

<ul> 
    <% @books.each do |book| %> 
    <li><%= book.name %></li> 
    <% end %> 
</ul> 

Để kích hoạt bộ nhớ đệm chỉ bit này, chỉ cần bọc nó trong cache:

<% cache do %> 
    <ul> 
    <% @books.each do |book| %> 
     <li><%= book.name %></li> 
    <% end %> 
    </ul> 
<% end %> 

Tất nhiên, đây không đặt tên bộ nhớ cache hoặc làm bất cứ điều gì thực sự đặc biệt với nó ... trong khi Rails sẽ tự động chọn một tên duy nhất cho đoạn bộ nhớ cache này, nó sẽ không thực sự hữu ích. Chúng ta có thể làm tốt hơn. Hãy sử dụng kỹ thuật key-based cache expiration của DHH và đặt tên bộ nhớ cache liên quan đến nội dung của nó.

<% cache ['book-list', *@books] do %> 
    <ul> 
    <% @books.each do |book| %> 
     <li><%= book.name %></li> 
    <% end %> 
    </ul> 
<% end %> 

Chuyển đối số vào bộ nhớ cache sẽ tạo khóa bộ nhớ cache từ đối số được cung cấp. Các chuỗi được truyền trực tiếp - vì vậy, ở đây, bộ nhớ cache sẽ luôn được bắt đầu bằng 'danh sách sách'. Điều này là để ngăn chặn va chạm bộ nhớ cache với những nơi khác mà bạn có thể đang lưu vào bộ nhớ đệm cùng một nội dung, nhưng với một chế độ xem khác. Đối với mỗi thành viên của mảng @books, Rails sẽ gọi cache_key: đối với đối tượng ActiveRecord, điều này sẽ tạo ra một chuỗi bao gồm mô hình, ID và chủ yếu là lần cuối đối tượng được cập nhật.

Điều này có nghĩa là khi bạn cập nhật đối tượng, khóa bộ nhớ cache cho đoạn này sẽ thay đổi. Nói cách khác, nó tự động bị hết hạn - khi một cuốn sách được cập nhật, câu lệnh cache này sẽ tìm kiếm một khóa không tồn tại, kết luận nó không tồn tại và điền nó với nội dung mới. Cũ, nội dung cũ sẽ kéo dài trong cửa hàng bộ nhớ cache của bạn cho đến khi bị trục xuất bởi bộ nhớ hoặc hạn chế tuổi tác (memcached thực hiện điều này tự động).

Tôi sử dụng kỹ thuật này trong một số ứng dụng sản xuất và nó hoạt động tuyệt vời. Để biết thêm thông tin, hãy xem 37signals post và để biết thông tin bộ nhớ đệm chung trong Rails, hãy xem Ruby on Rails caching guide.

+0

+1 trên splatting bộ sưu tập @books. Không bao giờ nghĩ về điều đó, tôi thường sẽ chỉ lấy bản ghi sách mới nhất được cập nhật trong toàn bộ bảng và sử dụng – cpuguy83

+0

Bạn cũng nên lưu vào bộ nhớ cache từng cuốn sách để một cuốn sách thay đổi không làm hỏng toàn bộ bộ nhớ cache. – cpuguy83

4

"Chỉ có hai vấn đề khó khăn trong Khoa học máy tính: vô hiệu hóa bộ nhớ cache và đặt tên cho mọi thứ".
- Phil Karlton

Caching


Các Rails Guide to caching có lẽ luôn luôn là một điểm khởi đầu tốt cho việc xây dựng trong chiến lược bộ nhớ đệm đường ray đã cung cấp.Dù sao ở đây có cách tiếp cận rất dễ dàng của tôi để bộ nhớ đệm

# _partial.html.erb 
<% cache(some_key, :expires_in => 1.week) do %> 
    <%# ... content %> 
<% end %> 

Bây giờ một số some_key thể được bất kỳ chuỗi miễn là nó là duy nhất. Nhưng sau đó một lần nữa cho phép cố gắng thông minh hơn một chút về nó và làm cho chìa khóa bằng cách nào đó phụ thuộc vào danh sách sách. Giả sử bạn thực sự chuyển vào mảng books một số truy vấn được trả về sau đó đường ray gọi cache_key trên mỗi mục nhập của nó và cuối cùng là tạo một khóa duy nhất cho bộ sưu tập này. Vì vậy, khi bộ sưu tập thay đổi các thay đổi quan trọng. Thats vì cache_key được triển khai trong ActiveRecord::Base và do đó có sẵn trên tất cả các Mô hình. Và hơn nữa nó thậm chí còn sử dụng dấu thời gian nếu có.

Nhưng sau đó lại điều này sẽ nhấn db mỗi khi có yêu cầu. Cùng trong mã:

# controller_method 
@weekly_books = Books.where 'condition' 

# _partial.html.erb 
<% cache(@weekly_books) do %> 
    <%# ... content %> 
<% end %> 

Để tránh bị đánh db để thường bạn cũng có thể bộ nhớ cache truy vấn tự của nó bằng cách gói gọi:

# Book.rb 
def self.weeklies 
    Rails.cache.fetch("book_weeklies", :expires_in => 1.day) do 
    Books.where 'condition' 
    end 
end 

# controller_method 
@weekly_books = Books.weeklies 

# _partial.html.erb 
<% cache(@weekly_books) do %> 
    <%# ... content %> 
<% end %> 
+0

Vấn đề nằm trong trang chủ của tôi Sách được phân trang. Tôi gửi sách được phân loại đến partials. Bây giờ nếu tôi sử dụng Books.weeklies, điều này sẽ không cung cấp các bản ghi được phân trang. Làm thế nào để đạt được điều đó? –

Các vấn đề liên quan