I have two ActiveRecord
models which have a HABTM association.
I want to write a scope
to get the orphan records using Arel.
My problem is that I couldn't find a method to retrieve the arel_table
of the association. Since the relation is HABTM, there is no model to call arel_table
on.
I have the following now (which works), but I make a new arel table with the name of the join table (retrieved by using the reflect_on_association
method).
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))
}
This produces the following SQL:
SELECT `teachers`.*
FROM `teachers`
WHERE (`teachers`.`id` NOT IN (SELECT `groups_teachers`.`teacher_id`
FROM `groups_teachers` ))
So is there any better way to retrieve the arel_table
instead of making a new one?
Unfortunately, I believe your solution is pretty much the cleanest there is right now and is, in fact, what the association itself does internally when instantiated:
https://github.com/rails/rails/blob/46492949b8c09f99db78b9f7a02d039e7bc6a702/activerecord/lib/active_record/associations/has_and_belongs_to_many_association.rb#L7
I believe the reflection.join_table they use vs reflection.options[:join_table] is only in master right now though.
If you know the name of the association and therefore the join table, which in this case it looks like you do, you should be able to call:
Arel::Table.new(:groups_teachers)
In my testing that returns Arel table of a habtm association. Thanks to this answer for pointing this out to me.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With