2012-01-05 22 views
5

Tôi có hai mô hình ActiveRecord có liên kết HABTM.Làm thế nào để có được bảng arel của một hiệp hội habtm?

Tôi muốn viết scope để nhận hồ sơ trẻ mồ côi bằng Arel.

Vấn đề của tôi là tôi không thể tìm thấy phương thức truy xuất số arel_table của liên kết. Vì mối quan hệ là HABTM, không có mô hình nào để gọi arel_table vào.

Hiện tại, tôi có thông tin sau (hoạt động), nhưng tôi tạo một bảng Arel mới với tên của bảng nối (được truy xuất bằng cách sử dụng phương thức 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)) 
} 

này tạo ra các SQL sau:

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

Vì vậy, có cách nào tốt hơn để lấy arel_table thay vì làm một cái mới?

+0

Lưu ý, tôi nghĩ rằng có một cách rõ ràng hơn để thực hiện việc này, xem câu trả lời của tôi bên dưới. – Andrew

Trả lời

3

Thật không may, tôi tin rằng giải pháp của bạn là khá nhiều sạch có ngay bây giờ và, trong thực tế, những gì các hiệp hội chính nó trong nội bộ khi khởi tạo:

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

Tôi tin rằng họ reflection.join_table sử dụng vs reflection.options [: join_table] chỉ có trong master ngay bây giờ.

2

Nếu bạn biết tên của hiệp hội và do đó bảng, mà trong trường hợp này có vẻ như bạn làm, bạn sẽ có thể để kêu gọi tham gia:

Arel::Table.new(:groups_teachers) 

Trong thử nghiệm của tôi mà trả Arel bảng một hiệp hội habtm. Cảm ơn this answer vì đã chỉ cho tôi điều này.

+0

Ít nhất là bây giờ (nhìn vào ARel 3.0.2 và AR 3.2) bạn có thể làm một số môn thể thao xấu xí như 'Groups.reflect_on_association (: giáo viên) .through_reflection.klass.arel_table', sẽ cung cấp cho bạn một đối tượng bị ràng buộc đúng. – Nicos

+0

Ví dụ nhanh nếu có ai nhầm lẫn! 'User.joins (: sports) .where (Arel :: Table.new (: sports_users) [: sport_id] .eq (SPORT_ID))' – Marrs

Các vấn đề liên quan