Verein für polymorphe belongs_to von einem bestimmten Typ

Ich bin relativ neu auf Schienen. Ich möchte hinzufügen, eine Assoziation zu einem Modell, das die polymorphe Assoziation, gibt aber nur Modelle eines bestimmten Typs, z.B.:

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

Habe ich versucht, eine Vielzahl von Kombinationen aus der Lektüre über die Verbände auf ApiDock aber nichts scheint genau das zu tun, was ich will. Hier ist die beste, die ich bisher:

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 will es um diesen test zu bestehen:

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

Den ersten test bestanden, aber Sie können nicht rufen Sie den Bezug direkt:

  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?

Dem Grund will ich es so machen, weil ich das konstruieren einen Bereich basierend auf der Analyse einer query-string inklusive Eintritt zu den verschiedenen Modellen/etc; der code verwendet, um zu konstruieren, der Umfang ist wesentlich komplexer als das oben es nutzt collection.reflections usw. Meine aktuelle Lösung funktioniert für das, aber es verletzt mich, ich kann nicht rufen Sie die Beziehungen, die direkt aus einer Instanz der Hinweis.

Konnte ich es lösen, indem man es in zwei Ausgaben: mit scopes direkt

  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ür note.volunteer/note.participation dass nur die Renditen note.subject wenn es die richtige subject_type (null sonst), aber ich dachte, in Schienen es muss einen besseren Weg?

  • Der etwas kryptischen {notes: {subject_type: "Volunteer"}} Klausel notes: denn sonst würde die Abfrage auf nicht-existierende volunteers.subject_type Spalte, das macht es die Abfrage auf notes.subjects_type. Ich sich entschieden haben, entspricht {'notes.subject_type': "Volunteer"} syntax; es erinnert mich auch an die notes sollte ein plural-Tabelle name, nicht die (manchmal singular) Verein name...
InformationsquelleAutor Benjie | 2014-02-18
Schreibe einen Kommentar