2010-05-14 6 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} 

을 다른 방법으로, 여기에 내가 당신의 응용 프로그램에 대한 몇 가지 있으리라 믿고있어, 나는 더 나은 그것을 할 것 방법 : 키가 블록을 평가 한 결과이며, 값이 원본 객체 어디에 해시를 반환 내가 #index_by 사용하고

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 %> 

공지 사항. ID로 페이지를 찾으려는 것처럼 보이기 때문에 해시를 사용하는 것이 좋습니다.

데이터베이스에 다소 집중적으로 작용한다는 점은 좋은 생각이며 언제나 염두에 두어야 할 점입니다. 반환 된 데이터의 대부분을 사용한다면 의미가 있습니다. 데이터의 작은 하위 집합 만 사용하는 경우에는 해당 개체의 모든 데이터를 다운로드하고 나중에 밀리 초 동안 가비지 수집시 삭제해야합니다.

관련 문제