Möglich, eine "polymorphe has_one" -Beziehung in Schienen zu haben?
Ich würde gerne etwas wie das hier tun:
Category
--------
- id
- name
Tag
--------
- id
- tag
Campaign
--------
- id
- name
- target (either a tag *or* a category)
Ist eine polymorphe Assoziation ist die Antwort hier? Ich kann nicht scheinen, um herauszufinden, wie es zu benutzen mit has_one :Ziel :da => :anvisierbare.
Grundsätzlich möchte ich-Kampagne.Ziel festgelegt werden, einen Tag oder eine Kategorie (oder möglicherweise ein anderes Modell in der Zukunft).
Kommentar zu dem Problem
Möglich, Duplikat der stackoverflow.com/questions/375083/...
Etwas anders, aber ist ja ähnlich.
InformationsquelleAutor der Frage markquezada | 2011-09-08
Du musst angemeldet sein, um einen Kommentar abzugeben.
Ich glaube nicht, dass Sie sind in der Notwendigkeit einer
has_one
Verein hier, derbelongs_to
sollte sein, was du bist suchen für.In diesem Fall würden Sie wollen, eine
target_id
undtarget_type
Spalte auf der Kampagnen-Tabelle erstellen, können Sie diese in einem rake mit einemt.references :target
nennen (wot
ist dietable
variable).Nun Kampagne verknüpft werden können, um entweder eine
Tag
oderCategory
und@campaign.target
zurückkehren würde, den entsprechenden.Den
has_one
Verein würde verwendet werden, wenn Sie einen foreign key auf die Zieltabelle verweist Sie zurück zu IhremCampaign
.Beispielsweise Ihre Tabellen hätte
Tag: id, tag, campaign_id
Category: id, category, campaign_id
hätte eine
belongs_to :campaign
Verband Sie beide. In diesem Fall hätten Sie zu verwendenhas_one :tag
undhas_one :category
, aber Sie konnte nicht, verwenden Sie eine generischetarget
an dieser Stelle.Macht das mehr Sinn?
BEARBEITEN
Seit
target_id
undtarget_type
effektiv Fremdschlüssel zu einer anderen Tabelle, IhreCampaign
gehört zu einem von Ihnen. Ich sehe Ihre Verwirrung mit dem Wortlaut, weil logischerweise dieCampaign
ist der container. Ich denke, man kann es alsCampaign
hat ein einziges Ziel, und das ist einTag
oder eineContainer
daher gehört es in eineTag
oderContainer
.Den
has_one
ist die Art zu sagen, die Beziehung definiert ist, die auf der Ziel-Klasse. Zum Beispiel, einTag
haben würde, verbunden sein, um die Kampagne durch einehas_one
Beziehung da gibt es nichts auf der tag-Klasse, identifiziert der Verband. In diesem Fall hätten Sieund ebenfalls für eine
Category
. Hier die:as
Schlüsselwort zu erzählen Schienen, die Assoziation bezieht sich zurück auf dasTag
. Schienen, die nicht wissen, wie um dies herauszufinden, im Voraus, weil es keinen Verein mit dem Namentag
auf dieCampaign
.Den anderen beiden Optionen, die möglicherweise weitere Verwirrung sind die
source
undsource_type
Optionen. Diese werden nur in der:through
Beziehungen, wo bist du eigentlich Beitritt in den Vereinthrough
einer anderen Tabelle. Die docs wohl beschreiben es besser, aber diesource
definiert der Verein name, undsource_type
wird dort verwendet, wo diese Vereinigung ist polymorph. Sie müssen nur dann verwendet werden, wenn die Ziel-Verband (auf der:through
Klasse) hat einen Namen, der nicht offensichtlich ist -- wie in dem Fall oben mittarget and
Tag -- und wir müssen sagen, Schienen die man zu verwenden.InformationsquelleAutor der Antwort Kristian PD
Antworten auf diese Fragen sind toll, aber ich wollte nur erwähnen, ein anderer Weg, um dasselbe zu erreichen. Was könnten Sie stattdessen tun ist, erstellen Sie zwei Beziehungen, wie zB.:
Die Validierung stellt sicher, dass Sie nicht versehentlich am Ende mit beiden Felder setzen, und die
target
Helfer ermöglicht polymorphe Zugriff auf die tag - /Kategorie.Den Vorteil, es zu tun wie dieser ist, dass Sie ein wenig mehr richtige Datenbank-schema, in dem Sie definieren können ordnungsgemäße foreign key-Einschränkungen, die auf die id-Spalte. Dies führt auch zu schöner und effizientere sql-Abfragen auf der Datenbank-Ebene.
InformationsquelleAutor der Antwort troelskn
Leichte Nachtrag: In der migration, wo Sie erstellt die
Campaign
Tabelle, diet.references :target
nennen sollte:polymorphic => true
(zumindest mit rails 4.2)InformationsquelleAutor der Antwort user5390702