2016-05-26 11 views
1

Ich habe eine Join-Tabelle lab_tests, die eine Liste der Tests speichert, die ein bestimmtes Labor mit dem Schema lab_id und test_id hat.Join Tabelle Active Record Query

Ich möchte eine Liste von Labors erhalten, die alle Tests haben, die in die Parameter übergeben werden.

Im Moment habe ich die folgenden Geltungsbereich -

scope :test_filter, lambda {|test_id| 
    return nil if test_id.blank? 
    where(:test_id => test_id) 
} 

Aber das gibt mir eine Liste der Labors mit mindestens einem Test. Wie kann ich eine Liste von Labors erhalten, die alle Tests in den angegebenen Parametern enthalten?

Antwort

1

Sie können den Trick mit GROUP BY und HAVING verwenden. Wenn Sie die Zuordnungstabelle für alle gewünschten test_id s filtern und sie nach lab_id gruppieren, dann ist die Anzahl der gruppierten Datensätze identisch mit der Anzahl der Tests. Sie sind also sicher, dass das Labor alle diese Tests umfasst (möglicherweise enthält es andere Tests) Tests, aber ich denke, dass es Ihnen nichts ausmacht).

Also, versuchen Sie so etwas wie dieses:

# Lab model: 
scope :with_tests, -> (test_ids) { 
    return Lab.none if test_ids.blank? 

    joins(:lab_tests). 
    where(lab_tests: { test_id: test_ids }). 
    group(:lab_id). 
    having("count(*) = ?", test_ids.count) 
} 

Hinweise:

  • Der Umfang eine none scope bei leerer test_ids zurückgibt. Dies ist ein besserer Ansatz als nil, da none ein normal verkettbarer Bereich ist, der auf die gleiche Weise wie andere Bereiche verwendet werden kann (die Verkettung nil würde eine Ausnahme auslösen).
  • Sie haben nicht angegeben, wo sich Ihr Bereich befindet, also dachte ich, das Lab-Modell könnte ein guter Platz sein - auf diese Weise gibt der Bereich die Labs mit mindestens die angegebenen Tests zurück.
  • Der Bereich verbindet sich in der Zuordnungstabelle und filtert nur die Datensätze mit der test_ids. test_ids sollte ein Array von Test-IDs sein, die im Labor gesucht werden. Die Bedingung wird als IN-Klausel in der WHERE-Bedingung des SQL ausgeführt.
  • Dann verwendet es den Gruppierungstrick - es gruppiert nach lab_id und gibt nur die Datensätze zurück, die die gleiche Anzahl an Tests in der Gruppe haben wie die Anzahl der Eingabetests. I.e. es gibt nur jene Labors zurück, die mindestens alle gegebenen Tests haben.
+0

funktionierte perfekt! Vielen Dank! –