2009-09-03 3 views
38

레일스 제휴가 열심히로드되었는지 확인하는 방법을 아는 사람이 있습니까?레일스 연관이 열심히로드되었는지 확인하는 방법은 무엇입니까?

내 상황 : 때로는 연관 중 하나가 열심히로드되고 때로는 그렇지 않은 결과 세트가 있습니다. eager-loaded가 아닌 경우 ActiveRecord의 find를 사용하여 연관을 찾아야합니다. 그것이 열심히로드되면, 나는 detect를 사용하고 싶다.

예를 들어, 항목 모델에 shipping_info 개체의 "has_many"배열이 있다고 가정 해보십시오. 그런 다음 : 항목이로드, 가장 효율적인 부하가 열망되어 있지 않은 경우

item.shipping_infos.detect { |si| si.region == "United States" } 

: 항목이로드 열망 경우

는 가장 효율적인 부하는

item.shipping_infos.where(region: "United States").first 

그러나 나는 그 여부를 알 수없는 한 열심히로드 된, 나는 레코드를 효율적으로 얻으려면 어떤 코드를 호출 해야할지 모르겠다. 열심히로드되지 않았을 때 첫 번째 방법을 사용하면 필요한 것보다 많은 DB 레코드를 조회해야합니다. 두 번째 방법을 열심히 읽었을 때 두 번째 방법을 사용하면로드 된 객체가 무시됩니다.

답변

41

item.shipping_infos.loaded?를 알려드립니다.

그래도 말 해 :이 경로는 광기에 이르게 ... #detect#find 사이에서 결정하는 loaded?을 테스트 코드를 작성하기 전에,이 인스턴스에게 무슨 일 다른 모든 것들에 비해 정말 사항을 확인하십시오.

이것이 앱에서 가장 느린 것이 아니라면 추가 코드 경로를 추가하면 불필요한 복잡성이 추가됩니다. 약간의 데이터베이스 작업을 낭비한다고해서 문제를 해결할 필요가 있다는 것을 의미하지는 않습니다. 측정 가능한 방식으로는 별 문제가되지 않을 수도 있습니다.

+0

감사합니다. Bryan. 나는 네가 어디에서 왔는지 이해한다. 이 특정 코드는 전체 앱에서 가장 자주 호출되는 partial에 존재합니다. 따라서 마이크로 세컨드에서 면도 할 경우 측정 가능한 차이가 있습니다. #loaded 줄거야? 시도. – wbharding

+9

이것은 has_many 연관에서만 작동합니다! belongs_to의 경우이 호출은 실제로 다른 객체를로드합니다 (따라서 항상 true가됩니다) – reto

2

Bullet gem.을 살펴보십시오. 이것은 열정적 인로드를 사용해야 할 때와 사용하지 말아야 할 때를 알려줍니다.

+0

아직 다른 DB 최적화를 거의 수행하지는 않았지만 불릿은 정말 유용하다고 입증되었습니다. 최소한 콘솔 출력에서 ​​불필요한 줄을 제거합니다. ;) – lime

+0

글 머리 기호 플러그인 링크가 작동하지 않습니다. –

3

로드 된 단일 연관이로드되었는지 감지 할 수 있습니다. foo? 예를 들어, shipping_info가 belongs_to 연관 일 경우 item.loaded_shipping_info? 열심히로드되었을 때 true를 반환합니다. 이상하게도, (레일즈 2.3.10에서)로드되지 않았을 때, false가 아닌 nil을 반환하는 것처럼 보입니다.

+3

이것은 Rails 3.1에서 삭제되었습니다 : https://github.com/rails/rails/issues/472 – Forrest

2

이 문제에 대한 해결 방법은 foo.association(:bla).loaded?해야하지만, 그것이 잘못 작동합니다 -이 체크 마크 협회 더러운 :

class Foo; has_one :bla, :autosave => true end 
foo.association(:bla).loaded? #=> false 
foo.save # saves foo and fires select * from bla 

그래서 액티브을 확장 다음 추가 한 :

module ActiveRecord 
    class Base 
    def association_loaded?(name) 
     association_instance_get(name).present? 
    end 
    end 
end 

과 지금 :

class Foo; has_one :bla, :autosave => true end 
foo.association_loaded?(:bla) #=> false 
foo.save # saves foo 
+0

이것이 여전히 문제가 아닌지 다시 확인하고 적절한 레일스 버전에 대한 답변을 업데이트하십시오. 나는 번식 할 수 없었다. –

+0

Rails 4.2.6에서 여전히 문제가 있습니다. Rails 5가 가지고 있는지 확실하지 않습니다. – Omnilord

+0

더러움으로 표시 한 결과는 무엇입니까? 단 하나의 추가 선택 진술? 아니면 더 해롭습니까? – lulalala

19

나는 item.association_ cache.keys는 열렬히로드 된 연관 목록을 제공합니다. 그럼 당신 item.association_cache.keys.include?: name_of_association

+1

완벽한 솔루션. Dabogert 당신은 왕이야 – Benj

+0

와우, 내가 이것을 놓쳤다는 것을 믿을 수 없어. 이는 연관이로드되지 않은 경우에 작동하지만 인 메모리 캐시가 있습니다 (예 : 연관을 사용하여 객체를 작성할 때). –

관련 문제