2016-01-10 5 views
11

Hier ist ein Beispiel:Wie kann ich in Ruby on Rails einen Bereich für eine has_many-Beziehung erstellen?

Lassen Sie mich sagen, ich habe ein Student-Objekt, das eine has_many-Beziehung mit ReportCard-Objekten hat. ReportCard-Objekte haben ein boolesches Feld namens "benotet", das angibt, dass sie benotet wurden. So wie es aussieht:

class Student < ActiveRecord 
    has_many :report_cards 
end 

class ReportCard < ActiveRecord 
    # graded :boolean (comes from DB) 
    belongs_to :student 
end 

Nun lassen Sie uns sagen, dass Sie einen Standardbereich erstellt werden soll, so dass, wenn ein Schüler keine gestaffelten ReportCards hat, möchten Sie alle von ihnen, um zu sehen, aber wenn sie mindestens ein abgestuft haben Reportcard , Sie wollen nur die abgestuften sehen. Nehmen wir an, Sie ordnen sie mit "seme_number" an.

Mit diesem Umfang auf Reportcard richtig funktioniert:

scope :only_graded_if_possible, ->(student) { where(graded: true, student: student).order(:semester_number).presence || order(:semester_number) } 

Aber ich will es der Standardbereich für Schüler sein, so habe ich versucht:

class Student < ActiveRecord 
    has_many :report_cards, ->{ where(graded: true).order(:semester_number).presence || order(:semester_number) } 
end 

aber das funktioniert nicht. Es wird keine report_cards zurückgeben, wenn eine einzige benotete report_card in der gesamten db vorhanden ist. Betrachtet man die Abfragen, die ausgeführt werden, führt es zuerst so etwas wie:

SELECT report_cards.* FROM report_cards WHERE reports_cards.graded = t ORDER BY semester_number ASC 

Ich denke, das muss die Gegenwart sein? Überprüfen Sie einen Teil der Anwesenheitsanfrage und stellen Sie fest, dass sie überhaupt nicht nach Student gefiltert ist! Also, wenn es eine einzige report_card ist, die abgestuft ist, die Kontroll Pässe und dann läuft er die folgende Abfrage, was zu bekommen zurückzukehren:

SELECT report_cards.* FROM reports_card WHERE report_card.student_id = 'student id here' AND report_card.graded = t ORDER BY semester_number 

Diese Abfrage würde eigentlich richtig sein, wenn der Student eine abgestuftes Bericht Karte hat, aber es ist immer leer, wenn er es nicht tut.

Ich nehme an, dass möglicherweise die Filterung auf Student später hinzugefügt wird. Also habe ich versucht, es irgendwie zu bekommen Schüler filtern rechts von der Fledermaus:

has_many :report_cards, ->{ where(graded: true, student: self).order(:semester_number).presence || order(:semester_number) } 

Das funktioniert nicht, entweder, weil es scheint, dass „selbst“ in diesem Bereich ist nicht der Student Objekt wie ich annehmen würde, aber eine Liste aller report_card-IDs Hier ist die Abfrage, die dieser ausführt:

SELECT report_cards.* FROM report_cards WHERE report_cards.graded = t AND report_cards.student_id IN (SELECT report_cards.id FROM report_cards) ORDER BY semester_number ASC 

Das ist nicht einmal nahe zu korrigieren. Wie kann ich das zur Arbeit bringen?

Ich denke, es kommt wirklich darauf an, dass jemand "self" (dh das aktuelle Student-Objekt) als Parameter in den Bereich "has_many" übernehmen kann. Vielleicht ist das nicht möglich.

+0

Welche Version von Rails verwenden Sie? – Dani

Antwort

2

Sie Objekt passieren kann Umfang als Parameter Lambda dieses

has_many :report_cards, -> (student) { ... } 
+0

erforderlich machen würde, wird von jedem Wechsel des Verein: student.report_cards auf den redundanten student.reports_cards (Student) das etwas, was ich zu vermeiden, bin versucht. – Mike

+0

Nein, tut es nicht. Gerade Active Record Magie. – Oleg

+0

Bitte erläutern. Das beantwortet meine Frage nicht. Jeder einzelne Verweis auf student.report_cards löst eine Ausnahme aus, weil die Anzahl der Parameter nicht mehr übereinstimmt. – Mike

1

Versuchen zu has_many:

class Student < ActiveRecord::Base 
    has_many :report_cards, ->{ where(graded: true).order(:semester_number).presence || unscoped.order(:semester_number) } 
end 
+0

habe '' Base' vergessen – trushkevich

0

ich in meinem Projekt bin mit dem ich ein Modell haben, die mit den Benutzern zugeordnet ist, :

Und in dem Benutzermodell erstellen Sie einen Bereich von only_deleted, die Ihre Benutzer zurückgibt, die sind gelöscht.

Verwandte Themen