2012-01-05 5 views
5

두 개의 ActiveRecord 모델에 HABTM 연관이 있습니다.habtm 연관의 arel 테이블을 얻는 방법?

Arel을 사용하여 고아 레코드를 가져 오려면 scope이라고 쓰고 싶습니다.

제 문제는 연관의 arel_table을 검색하는 방법을 찾을 수 없다는 것입니다. 관계가 HABTM이므로 arel_table을 호출 할 모델이 없습니다.

다음은 작동합니다 (작동).하지만 reflect_on_association 메서드를 사용하여 검색 한 조인 테이블의 이름을 사용하여 새로운 arel 테이블을 만듭니다.

SELECT `teachers`.* 
FROM `teachers`  
WHERE (`teachers`.`id` NOT IN (SELECT `groups_teachers`.`teacher_id` 
           FROM `groups_teachers`)) 

그래서 arel_table를 검색하는 대신 새로운 하나를 만들기 위해 더 좋은 방법이 :

scope :orphans, lambda { 
    teachers = arel_table 
    join_table = Arel::Table.new(reflect_on_association(:groups).options[:join_table]) 

    join_table_condition = join_table.project(join_table[:teacher_id]) 
    where(teachers[:id].not_in(join_table_condition)) 
} 

이 다음과 같은 SQL을 생성? 불행하게도

+0

참고, 나는 이것을 할 수있는 더 깨끗한 방법이 있다고 생각합니다. 내 대답은 아래를 참조하십시오. – Andrew

답변

3

, 당신의 솔루션은 거의가 지금하고 인스턴스화 할 때 협회 자체가 내부적으로 무엇을, 사실입니다 깨끗한 믿습니다 :

https://github.com/rails/rails/blob/46492949b8c09f99db78b9f7a02d039e7bc6a702/activerecord/lib/active_record/associations/has_and_belongs_to_many_association.rb#L7

내가 reflection.join_table을 믿고 그들이 vs reflection.options [: join_table]을 사용하는 것은 지금 당장 마스터에만 있습니다.

2

당신은 협회의 이름을 알고, 따라서이 경우에는 당신처럼, 당신은 전화를 할 수 있어야한다 보인다 테이블, 조인 경우 : Arel 테이블을 반환 내 테스트에서

Arel::Table.new(:groups_teachers) 

을 habtm 협회. 이 점을 지적 해 주신 this answer에게 감사드립니다.

+0

적어도 지금까지 ARel 3.0.2와 AR 3.2를 보았을 때'Groups.reflect_on_association (: teachers) .through_reflection.klass.arel_table'과 같은 추악한 육상 경기를 할 수 있습니다.이 운동은 제대로 바운드 된 객체를 제공합니다. – Nicos

+0

누군가가 혼란스러운 경우 빠른 예! 'User.joins (: sports) .where (Arel :: Table.new (: sports_users) [: sport_id] .eq (SPORT_ID))' – Marrs