3

이 루비/레일은 항상 구성 저 퍼즐 :액티브 쿼리 체인

User.where(:name => "Thiago").limit(3).using(:slave_one) 

이에서 실행해야합니다 왼쪽에서 오른쪽으로, 각각의 연속적인 호출이 수신기를 가질 수 있도록. 먼저 User 클래스로 시작하여 where을 호출하여 ActiveRecord::Relation의 인스턴스를 반환합니다. 해당 인스턴스에서 limit이 호출되고 ActiveRecord::Relation의 다른 인스턴스가 반환됩니다. 그런 다음 using이 해당 인스턴스에서 호출됩니다 (샤드를 선택하는 경우). 모든 것은 ActiveRecord::Relation 개체 안에 SQL 쿼리를 작성합니다. 내 질문은 "쿼리의 실제 실행을 트리거하는 것"입니다. 체인에서 체인의 특정 지점에서 실행할 수 없기 때문에 체인에서 쿼리를 추가로 수정할 수 있습니다. using이 반환 된 후에도 추가 메서드가 체인에 연결되어 있는지 여부를 알 수 없기 때문에 쿼리를 실행할 수 없습니다. 분명히 그것을 구축 한 후에 쿼리를 실행하므로 쿼리가 실제로 어떻게 호출됩니까?


감사합니다 ... 이제 체인의 메소드 이름에 "의미"가 있음을 알았습니다. 일부는 빌드 될 u 리를 추가로 수정합니다. 마지막 및 마지막 부분은 데이터를 가져올 필요가있는 형식 일 수 있습니다.

답변

7

ActiveRecord :: Relation은 데이터를 요청하기 전까지는 데이터베이스와 통신하지 않습니다. 예를 들어 :

def x(*args) 
    relation = clone 
    # merge args into relation 
    relation 
end 

그래서 관계 : 당신은 액티브 :: 관계를 살펴있는 경우

User.where(:name => "Thiago").limit(3).using(:slave_one).count 
# talks to the database here ----------------------------^^^^^ 

, 당신은 ActiveRecord::QueryMethods을 포함하고 물건의 대부분은 다음과 같이이 모양의 것을 볼 수 있습니다 쿼리를 실행해야하는 작업을 수행 할 때까지 조각으로 쿼리를 작성합니다. 적절한 SQL을 만들고, 데이터베이스로 보내고, 데이터베이스가 되돌려 보내는 것과 함께 (이론적으로) 유용한 것을 할 것입니다.

r1 = User.where(:name => 'Pancakes') 
r2 = r1.limit(3) 

을하고 그냥 세를 잡기 위해 모든 일치 또는 r2을 잡아 r1를 사용

또한이 같은 일을 할 수 있도록 QueryMethods 방법의 각 복제 및 수정 된 관계를 반환 있습니다 .

3

이 구문 (쿼리를 빌드하는 동안 쿼리가 실행되지 않는)은 의도적입니다. Lazy Loading이라고합니다.

처음으로 관계에 데이터를 요청하면 쿼리가 실행됩니다. IE 당신이 있다면 :

@users = User.where(:name => "Thiago").limit(3).using(:slave_one) 
@users.first.name #the query executes here 

는 일반적으로이 실행하려고 할 때 자신의 쿼리에서 데이터를 호출하여 뷰 템플릿의 첫 번째 행.