0

has_many.rb

  has_many :child_attendances, -> (attendance) {
    includes(:activity).references(:activity).
      where(activities: {parent_activity_id: attendance.activity_id}).
      where(
        Attendance.arel_table.grouping(
          Attendance.arel_table[:attendant_id].eq(attendance.attendant_id).
          and(Attendance.arel_table[:attendant_type].eq(attendance.attendant_type))
        ).
        or(Attendance.arel_table[:tag_code].eq(attendance.tag_code))
      )
  }, class_name: 'Attendance', dependent: :destroy

methods.rb

  def self.child_attendances(attendance)
    includes(:activity).references(:activity).
    where(activities: {parent_activity_id: attendance.activity_id}).
    where(
      Attendance.arel_table.grouping(
        Attendance.arel_table[:attendant_id].eq(attendance.attendant_id).
          and(Attendance.arel_table[:attendant_type].eq(attendance.attendant_type))
      ).
        or(Attendance.arel_table[:tag_code].eq(attendance.tag_code))
    )
  end

  def child_attendances
    self.class.child_attendances(self)
  end

When using has_many.rb

-- attendance.child_attendances.to_sql
SELECT "attendances"."id" AS t0_r0 FROM "attendances" LEFT OUTER JOIN "activities" ON "activities"."id" = "attendances"."activity_id" WHERE "activities"."parent_activity_id" = 654 AND (("attendances"."attendant_id" IS NULL AND "attendances"."attendant_type" IS NULL) OR "attendances"."tag_code" = '123456789') AND "attendances"."attendance_id" = 164513

It appends "attendances"."attendance_id" = 164513, and attendance_id is not a valid column for Attendance.

When using methods.rb

-- attendance.child_attendances.to_sql
SELECT "attendances"."id" AS t0_r0 FROM "attendances" LEFT OUTER JOIN "activities" ON "activities"."id" = "attendances"."activity_id" WHERE "activities"."parent_activity_id" = $1  AND (("attendances"."attendant_id" IS NULL AND "attendances"."attendant_type" IS NULL) OR "attendances"."tag_code" = '123456789')  [["parent_activity_id", 654]]

How to make the other snippet into a has_many? Rails seems to always look for a primary_key and foreign_key to make the join, when using has_many.

Rafael Oliveira
  • 2,823
  • 4
  • 33
  • 50

1 Answers1

0

According to https://stackoverflow.com/a/34444220 what I was trying to do does not make sense to be built using has_many, so I'm sticking with an instance method.

  def child_attendances
    self.class.includes(:activity).references(:activity).
    where(activities: {parent_activity_id: activity_id}).
    where(
      Attendance.arel_table.grouping(
        Attendance.arel_table[:attendant_id].eq(attendant_id).
          and(Attendance.arel_table[:attendant_type].eq(attendant_type))
      ).
        or(Attendance.arel_table[:tag_code].eq(tag_code))
    )
  end
Community
  • 1
  • 1
Rafael Oliveira
  • 2,823
  • 4
  • 33
  • 50