Mam modelowane, użytkownik ma obecność w wydarzeniu.Aktywne łańcuchowanie zakresu rekordu, ignorowanie złączeń, jeśli jest już połączone
class User
has_many :attendances
has_many :events, through: :attendances
class Event
has_many :attendances
scope :is_attending, -> { joins(:attendances).where(attendances:{attend_status: Attendance.attend_statuses[:attending] })}
class Attendance
belongs_to :event
belongs_to :user
enum attend_status: { attending: 0, not_attending: 1}
Moje pytanie dotyczy zapytań o określone zakresy i najlepszych praktyk.
Umieściłem większość moich zapytań o zakres w Wydarzeniu.
Chcę uzyskać wszystkie zdarzenia dla określonego użytkownika, gdzie attend_status = 0
user = User.find(...)
user.events.is_attending
Logicznie to myślę, to brzmi najlepiej i najrozsądniej
jednak, że dałoby mnie podwójny INNER DOŁĄCZ
SELECT "events".* FROM "events"
INNER JOIN "attendances" "attendances_events" ON "attendances_events"."event_id" = "events"."id"
INNER JOIN "attendances" ON "events"."id" = "attendances"."event_id"
WHERE "attendances"."user_id" = $1 AND "attendances"."attend_status" = 0
Oczywiście tworzy to duplikaty, które nie są tym, czego chciałem.
Więc opcje wiem, że mogę zrobić
1) Użyj MERGE
Event
scope :for_user, -> (user){ joins(:attendances).where(attendances: {user: user})}
następnie wywołać
Event.for_user(user).merge(Event.is_attending)
który daje mi sql
SELECT "events".* FROM "events" INNER JOIN "attendances" ON "attendances"."event_id" = "events"."id" WHERE "attendances"."user_id" = 59 AND "attendances"."attend_status" = 0
to co Chcę. Ale wydaje się to okropną składnią i jest mylące.
2) wykorzystanie obejmuje
Jeśli używam zawiera zamiast przyłączyć, nie dostać duplikat przyłączyć. Ponieważ ładuje zdarzenia osobno i jest wystarczająco inteligentny, aby nie powielać.
Event
scope :is_attending, -> { includes(:attendances).where(attendances: {attend_status: Attendance.attend_statuses[:attending] })}
Jednak nie chcę dużego ładunku.
3) przyjąć tabela jest już dołączył poza zakresem
Wreszcie mogę założyć, że tabela jest już dołączył poza wywołaniem zakres,
Event
scope :is_attending, -> { where(attendances: {attend_status: Attendance.attend_statuses[:attending] })}
Ale to wydaje się trochę głupie projekt do mnie i sprawia, że ten nazwany zakres jest mniej przydatny do ponownego wykorzystania.
więc moje pytania
1) Jakie jest najlepsze podejście do tego? Najbardziej logiczne user.events.is_attending
jest tym, którego idealnie chcę użyć.
2) Czy istnieje sposób na poinformowanie Rekordu Aktywnego, aby ignorował połączenia, jeśli już się zdarzyły?