2012-09-06 3 views
0

나는 레일 3 웨이를 읽고 있었다 그리고 책에 설명 사항에 따라 CollectionAssociation.include?CollectionAssociation.include가 있습니까? 데이터베이스에 레코드가 있는지 확인합니다.

의 동작 확인되었다 : 공급 된 기록이 협회 모음에있는 경우

여부를 확인하기을하고 아직도 그 내부 데이터베이스 테이블에 존재합니다.

DB가 검사되었지만 검사하지 않는 것처럼 보이는 몇 가지 테스트를합니다.

> book = Book.first 
=> #<Book id: 1, title: "Programming Ruby"... 
> last_chapter = book.chapters.last 
=> #<Chapter id: 2, title: "Chapter 2", book_id: 1, 
> b.chapters.include?(last_chapter) 
=> true 
> last_chapter.destroy 
    DELETE FROM "chapters" WHERE "chapters"."id" = ? [["id", 2]] 
=> #<Chapter id: 2, title: "Chapter 2", book_id: 1, 
> b.chapters.include?(last_chapter) 
=> true   
> book.chapters.reload 
=> [#<Chapter id: 1, title: "Chapter 1", book_id: 1,...] 
> b.chapters.include?(last_chapter) 
=> false 

소스 코드를 확인한 결과 조건부로로드되는 것으로 보이는 load_target if options[:finder_sql] 행을 발견했습니다.

DB에 레코드가 존재하는지 확인하기 위해 DB에 액세스 할 수 있는지 알고 있습니까?

답변

1

레일즈는 느린로드와 메모를 사용합니다.

즉, 처음으로 getter를 호출 할 때까지 b.chapters에는 장이로드되지 않습니다.

이후 챕터를 파괴해도 메모 작성으로 인해 include? 테스트가 변경되지 않습니다. Rails는 장에있는 장을 다시로드하지 않습니다. 따라서이 장이 더 이상 책에 없다는 것을 알 수 없습니다.

참고 include?은 (Enumerable/Array 개체 정의되지만 ActiveRelation 객체에 직접 구현되지 않음)에 자동 레일 배열로 ActiveRelation 객체 book.chapters 캐스트 발생할 것이다. 따라서 include?은 먼저 챕터 배열을 가져온 다음 해당 챕터가 배열에 포함되어 있는지 확인합니다.

(ActiveRecord 개체에서)을 명시 적으로 호출하면 레일에 특정 개체가 다시로드되어 책의 장의 캐싱이 제거되고 실제 장이 다시로드됩니다.

  • 다시로드하려면 reload 번으로 전화를 걸지 않는 한 메모 생성 기능을 해제 할 수 없습니다.
  • 예를 들어, includes을 사용하여 지연로드 대신 eager-load라고 알릴 수 있습니다. book = Book.includes(:chapters).first. 이것은 Rails가 책을로드하는 동시에 모든 장을로드한다는 것을 의미합니다. book.chapters는 최신, 당신이 books.chapters.delete(book.chapters.last) 또는 books.chapter_ids.delete(book.chapter_ids.last)를 호출 할 수 있음을 보장하면서

는 장을 삭제합니다. 이 메소드를 사용하면 Rails는 더 이상 콜렉션에 없다는 것을 알기 위해 데이터베이스를 다시 질의 할 필요가 없다.

+0

통찰력있는 답변에 감사드립니다. 많은 것을 이해하는 데 많은 도움이되었습니다. –

+0

그러나'include?'메소드가 DB에 충돌하는 시나리오는 여전히 남아 있습니까? –

+0

'include?'(또는 배열에 작용하는 다른 어떤 메소드)는'chapters'가 아직로드되지 않은 경우에만 DB에 접근합니다. 'chapters'는 느린로드로 인해 처음으로 호출 할 때까지로드되지 않습니다. "처음으로 getter를 부를 때"라고 말했을 때, 나는 book.chapters를 호출했다. 이것은 book을 얻는 방법이다. – ronalchn

관련 문제