2010-05-14 100 views
1

我對於活躍記錄中熱切加載的機制有點困惑。比方說,一個Book模型有很多Pages我取使用此查詢一本書:幫我理解Rails急切加載

@book = Book.find book_id, :include => :pages 

現在這個地方我很困惑。我的理解是,@book.pages已經加載,不會執行另一個查詢。但是,假設我想找到特定頁面,我該怎麼辦?

@book.pages.find page_id 

# OR... 

@book.pages.to_ary.find{|p| p.id == page_id} 

我說得對不對在想,第一個例子將執行另一個查詢,因此使預先加載沒有意義的,或者是活動記錄足夠聰明的知道,它並不需要做另一個查詢?

另外,我的第二個問題,是否有一種說法,在某些情況下,在數據庫上進行加載更爲緊張,有時多個小型查詢會更有效,即單個大型查詢?

感謝您的想法。

回答

2

當ActiveRecord急切地加載一個關聯時,在對象的深處會發生什麼是一個實例變量被設置。就是這樣,沒有魔法。 Enumerable和ActiveRecord :: AssociationProxy提供的所有方法只是查看實例變量,以瞭解它是否已加載,然後繼續進行業務。

當你調用#find時,你沒有加載集合:你正在尋找一個特定的實例。你不是在和收藏本身談話。

你的第二個例子是要走的路,但我會做不同的是:

@book.pages.detect {|p| p.id == page_id} 

另外,在這裏,我假設你的應用程序的一些東西,我會做在更好方式:

class BooksController < ApplicationController 
    def show 
    @book = Book.find(params[:id], :include => :pages) 
    @pages_by_id = @book.pages.index_by(&:id) 
    end 
end 

# app/views/books/show.html.erb 
Page: <%= @pages_by_id[page_id].number %> 

通知我使用#index_by,其中鍵是評價塊的結果,和的值是原始對象返回一個散列。由於您似乎只想通過ID查找頁面,因此有一個哈希值是有意義的。

你對於在數據庫上或多或少強化的觀點是一個很好的觀點,並且始終牢記在心。如果您將使用大部分返回的數據,這將是有道理的。如果你只使用一小部分數據,那麼下載這些對象的所有數據沒有意義,只能在幾毫秒後將它們扔到垃圾收集處。