Как получить таблицу arel ассоциации habtm?

У меня есть две модели ActiveRecord с ассоциацией HABTM.

Я хочу написать scope, чтобы получить потерянные записи с помощью Arel.

Моя проблема в том, что я не смог найти способ получить arel_table ассоциации. Поскольку отношение является HABTM, нет модели для вызова arel_table.

Теперь у меня есть следующее (что работает), но я создаю новую таблицу arel с именем таблицы соединений (полученной с помощью метода reflect_on_association).

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:

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

Итак, есть ли лучший способ получить arel_table вместо создания нового?


person Maher4Ever    schedule 05.01.2012    source источник
comment
Обратите внимание: я думаю, что есть более чистый способ сделать это, см. мой ответ ниже.   -  person Andrew    schedule 19.11.2012


Ответы (2)


К сожалению, я считаю, что ваше решение в значительной степени самое чистое из существующих на данный момент, и на самом деле это то, что делает сама ассоциация внутри себя при создании экземпляра:

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

Я считаю, что Reflection.join_table, который они используют, по сравнению с Reflection.options[:join_table] сейчас находится только в мастере.

person Mike Auclair    schedule 26.06.2012

Если вы знаете имя ассоциации и, следовательно, таблицу соединений, что в данном случае похоже на то, что вы знаете, вы сможете вызвать:

Arel::Table.new(:groups_teachers)

В моем тестировании это возвращает таблицу Arel ассоциации habtm. Спасибо этому ответу за указание мне на это.

person Andrew    schedule 19.11.2012
comment
По крайней мере, к настоящему времени (смотря на ARel 3.0.2 и AR 3.2) вы можете делать некоторые уродливые упражнения, такие как Groups.reflect_on_association(:teachers).through_reflection.klass.arel_table, которые должны дать вам правильно связанный объект. - person Nicos; 18.11.2013
comment
Быстрый пример, если кто-то запутался! User.joins(:sports).where(Arel::Table.new(:sports_users)[:sport_id].eq(SPORT_ID)) - person Marrs; 25.08.2016