2012-03-01 3 views
5

당신을 위해 그것을 시각화합시다.ActiveRecord는 체인에서 마지막 메서드 호출을 어떻게 감지합니까?

특별한 것은 없습니다. 그냥 간단한 메서드 호출. 이제 다음 예제를 살펴보십시오.

class Product < ActiveRecord::Base 
    def method_missing 
    end 
end 

Product.first.title 
#=> nil 

Product.first 
Product.first.title 
#=> "My sample product" 

어떻게 가능합니까? 어떤면에서 그들은 메소드 체인의 끝을 결정하고 그에 따라 행동합니까? 적어도 내 이론.

누구든지이 동작을 설명 할 수 있습니까?

답변

7

irb을 사용하여 아티팩트를 조사하고 있습니다.

이 말할 때 :

> Product.first.title 
#=> nil 

귀하가 method_missing가에 호출 될 title 방법을 게으른 -로드 당신은 nil를 얻을.

당신이 말할 때이 : 당신은 효과적으로을하고있는

> Product.first 

: 첫 번째 제품 인스턴스가로드됩니다 다음 irb 그것에 inspect를 호출하고 AR이 추가됩니다

> p = Product.first; puts p.inspect 

접근 자 메소드. 결과적으로 Product는 title 메소드를 갖게됩니다. 따라서,이 일을 : Product.first.title 전화를위한 진짜 title 방법이있을 것 같은

> Product.first 
> Product.first.title 

은 모든 method_missing를 호출하지 않습니다.

당신은 다음과 같이 다시 시도하십시오 :

> Product.first; nil 
> Product.first.title 

당신은이 nil의를 볼 수 있습니다.


는 지금까지 체인이가는대로, 액티브 정말 어떤 방법이 자연적으로 호출하는 데이터베이스에서 실제 데이터를 필요로하지 않는 몇 가지 단지이다, 끝을 감지하지 않습니다.

당신이 whereorder가, 또는 다른 쿼리 방법 중 하나는, 당신이 되돌려 ActiveRecord::Relation 인스턴스를 얻을 호출하는 경우 해당 관계 개체의 쿼리 방법과 범위 체인 이상을 할 수 있습니다. 예를 들어, (액티브는 :: 관계는 ActiveRecord::QueryMethods를 포함하여 얻을 수)과 같습니다 where : 그래서 그냥, 현재 쿼리의 복사본을 만드는 사본에 몇 가지를 추가하고, 당신에게 사본을 제공

def where(opts, *rest) 
    return self if opts.blank? 

    relation = clone 
    relation.where_values += build_where(opts, rest) 
    relation 
end 

뒤로.

전화 할 경우 first, last, to_a, allEnumerable 방법 중 하나 (당신이 each를 호출 즉), ...특정 인스턴스에 대해 질문하면 ActiveRecord는 해당 모델 인스턴스를 실현하기 위해 쿼리를 실행해야합니다. 예를 들어, ActiveRecord::Relation#to_a은 다음과 같습니다

def to_a 
    logging_query_plan do 
    exec_queries 
    end 
end 

all는 래퍼 주위 to_a에 불과하다.

ActiveRecord는 실제로 체인의 끝 부분을 알지 못합니다. 데이터베이스에서 아무 것도로드하지 않고 체인이 끝나는 곳에서 이 나와서 데이터를 검색한다고 말하면됩니다..

+0

나는 그것이 체인의 끝을 감지한다고 생각한다 : 그것은 당신이 파인더 프록시 객체를 다시 얻지 못하는 곳이다! – phoet

+0

이것은 질문에 관한 것이 아닙니다. 문제는''''Product.first.title'''은 모델 내에서''method_missing'''가 사용될 때''''Product.first'''가 호출 될 때까지''nil''을 반환하는 이유입니다. ''''Product.first''를 호출하면 title은'''My sample blog''를 반환합니다. – user544941

+0

@ user544941 : 아, 나는 그가 묻는 것을 본다 : 무엇이 그의 "method_missing"을 대체하거나 우회하는지. –

관련 문제