Assoziation für polymorph gehört zu einem bestimmten Typ

Ich bin relativ neu in Rails. Ich möchte einem Modell, das die polymorphe Assoziation verwendet, eine Assoziation hinzufügen, aber nur Modelle eines bestimmten Typs zurückgeben, z.

class Note < ActiveRecord::Base
  # The true polymorphic association
  belongs_to :subject, polymorphic: true

  # Same as subject but where subject_type is 'Volunteer'
  belongs_to :volunteer, source_association: :subject
  # Same as subject but where subject_type is 'Participation'
  belongs_to :participation, source_association: :subject
end

Ich habe eine Vielzahl von Kombinationen aus dem Lesen der Assoziationen auf ApiDock ausprobiert, aber nichts scheint genau das zu tun, was ich will. Hier ist das Beste, was ich bisher habe:

class Note < ActiveRecord::Base
  belongs_to :subject, polymorphic: true
  belongs_to :volunteer, class_name: "Volunteer", foreign_key: :subject_id, conditions: {notes: {subject_type: "Volunteer"}}
  belongs_to :participation, class_name: "Participation", foreign_key: :subject_id, conditions: {notes: {subject_type: "Participation"}}
end

Und ich möchte, dass es diesen Test besteht:

describe Note do
  context 'on volunteer' do
    let!(:volunteer) { create(:volunteer) }
    let!(:note) { create(:note, subject: volunteer) }
    let!(:unrelated_note) { create(:note) }

    it 'narrows note scope to volunteer' do
      scoped = Note.scoped
      scoped = scoped.joins(:volunteer).where(volunteers: {id: volunteer.id})
      expect(scoped.count).to be 1
      expect(scoped.first.id).to eq note.id
    end

    it 'allows access to the volunteer' do
      expect(note.volunteer).to eq volunteer
    end

    it 'does not return participation' do
      expect(note.participation).to be_nil
    end

  end
end

Der erste Test ist erfolgreich, aber Sie können die Relation nicht direkt aufrufen:

  1) Note on volunteer allows access to the volunteer
     Failure/Error: expect(note.reload.volunteer).to eq volunteer
     ActiveRecord::StatementInvalid:
       PG::Error: ERROR:  missing FROM-clause entry for table "notes"
       LINE 1: ...."deleted" = 'f' AND "volunteers"."id" = 7798 AND "notes"."s...
                                                                    ^
       : SELECT  "volunteers".* FROM "volunteers"  WHERE "volunteers"."deleted" = 'f' AND "volunteers"."id" = 7798 AND "notes"."subject_type" = 'Volunteer' LIMIT 1
     # ./spec/models/note_spec.rb:10:in `block (3 levels) in <top (required)>'
Warum?

Der Grund, warum ich das so machen möchte, ist, dass ich einen Bereich konstruiere, der auf dem Parsen einer Abfragezeichenfolge basiert, einschließlich des Verbindens mit verschiedenen Modellen / etc .; Der Code, der zum Erstellen des Gültigkeitsbereichs verwendet wird, ist erheblich komplexer als der oben beschriebene - er verwendetcollection.reflectionsusw. Meine aktuelle Lösung funktioniert dafür, aber es beleidigt mich, dass ich die Relationen nicht direkt von einer Instanz von Note aus aufrufen kann.

Ich könnte es lösen, indem ich es in zwei Punkte aufspalte: direktes Verwenden von Bereichen

  scope :scoped_by_volunteer_id, lambda { |volunteer_id| where({subject_type: 'Volunteer', subject_id: volunteer_id}) }
  scope :scoped_by_participation_id, lambda { |participation_id| where({subject_type: 'Participation', subject_id: participation_id}) }

und dann nur mit einem Getter fürnote.volunteer/note.participation das kommt gerade zurücknote.subject wenn es das recht hatsubject_type (nil sonst) aber ich dachte bei Rails muss es einen besseren weg geben?

Antworten auf die Frage(4)

Ihre Antwort auf die Frage