2010-08-03 3 views
9

Ist es für ein Modell möglich, zu gehören, zwei Modelle und eine verschachtelte Beziehung?kann "Angle_to" zwei andere Modelle modellieren und haben eine verschachtelte Beziehung?

also von dem, was ich will

class trainer 
has_many :appointments 
end 

class appointment 
belong_to :trainer, :customer 
end 

class customer 
has_many :appointments 
end 

im Moment habe ich nur die Kunden und Termin-Modelle, die verschachtelt sind, zB von dem, was ich habe:

Methode erstellen sieht wie folgt aus:

def create 
    @appointment = @customer.appointments.build(params[:appointment]) 

    respond_to do |format| 
     if @appointment.save 
     format.html { redirect_to([@customer, @appointment], :notice => 'Appointment was successfully created.') } 
     format.xml { render :xml => @appointment, :status => :created, :location => @appointment } 
     else 
     format.html { render :action => "new" } 
     format.xml { render :xml => @appointment.errors, :status => :unprocessable_entity } 
     end 
    end 
    end 

in Routen ich habe:

map.resources :patients, :has_many => [ :appointments, :visits ] 

ist es möglich, 2 verschachtelte Beziehungen für 1 Modell zu haben? Womit würde ich meine create Methode ändern müssen, wenn der Termin auch dem Trainer und dem Kunden gehört? Unter der Annahme,

dank

Antwort

19

, dass Sie Active verwenden: gehören ein Modell zu haben, um mehr als ein anderes Modell ist natürlich möglich (aber Sie für jede Beziehung eine belongs_to Anweisung angeben müssen).

Eine angines_to-Beziehung bedeutet nicht unbedingt, dass der Datensatz tatsächlich diesen anderen Datensatz enthält; es kann auch Null sein. So können Sie Termine haben, die zu einem Trainer gehören, aber keinen Kunden und umgekehrt.

Eigentlich können Sie sogar weder einen Trainer noch einen Kunden oder sowohl einen Trainer noch einen Kunden auf diese Weise haben - wenn dies Ihre Geschäftslogik verletzt, möchten Sie vielleicht eine Validierung hinzufügen, um dies zu verhindern.

Ihre vorhandene Controller-Create-Methode sollte weiterhin so funktionieren, wie sie ist. Sie müssen lediglich die Verarbeitung der Trainerdatensätze hinzufügen. Sie können sogar den gleichen Controller verwenden, um die Terminvereinbarung für Trainer und Kunden durch Abstrahieren von Trainern und Kunden, z. in einer Person wie folgt aus:

class AppointmentsController < ApplicationController 

    def create 
    @appointment = person.appointments.build(params[:appointment]) 
    # ... 
    end 

protected 

    def person 
    @person ||= 
     if params[:trainer_id] 
     Trainer.find(params[:trainer_id]) 
     elsif params[:customer_id] 
     Customer.find(params[:customer_id]) 
     end 
    end 
end 

Auf diese Weise können Sie die gleiche AppointmentsController für beide Routen

# Use AppointmentsController for /trainers/123/appointments 
# as well as for /customers/123/appointments 
map.resources :trainers, :has_many => :appointments 
map.resources :customers, :has_many => :appointments 

Natürlich verwenden das macht nur Sinn, wenn die Logik und Blick hinter Trainer Termine und Kundentermine sind fast gleich. Wenn nicht, können Sie auch andere Controller verwenden

# Use TrainerAppointmentsController for /trainers/123/appointments and 
# CustomerAppointmentsController for /customers/123/appointments 
map.resources :trainers do |trainer| 
    trainer.resources :appointments, :controller => 'trainer_appointments' 
end 
map.resources :customers do |customer| 
    customer.resources :appointments, :controller => 'customer_appointments' 
end 
+0

+ 1 brillante Antwort! Danke. nur eine frage, wenn ich den termin über die kundenseite/ansicht erstelle. Wie füge ich die Trainer ID zum Termin hinzu? Kann ich einfach alle Trainer in die Ansicht laden und dem Benutzer erlauben, einen Trainer aus dem Drop-Down-Menü auszuwählen und dann die Trainer-ID der Trainer-ID zuzuweisen, die im Termin abgelegt wurde? –

+0

Sie haben Fragen zum trainer_id-Parameter oder zum Datensatzattribut? Der Parameter trainer_id wird durch die verschachtelte Ressourcenroute festgelegt. '/ trainers/123/termings' sets' params [: trainer_id] 'bis 123,'/customers/123/termings' sets 'params [: customer_id]' bis 123. Das Attribut trainer_id auf dem Terminkalender wird von der has_many gesetzt Verband. '@Appointment = person.appointments.build' wird automatisch '@ termin.trainer_id' oder' @ termination.customer_id' auf 'person.id' gesetzt, je nachdem, welcher Klassenperson es ist (um die Standardeinstellungen zu ändern, gibt es eine: foreign_key-Option für gehört). – Zargony

+0

Lassen Sie mich sagen, ich gehe zu einem Kundenprofil und erstellen Termin von seinem Profil (es wird die ID von den customer_id params abholen) aber wie kann ich dann diesen Termin einen Trainer zuweisen, der für diesen Termin verantwortlich sein wird. Wenn ich 10 Trainer habe, wie setze ich den Termin auf einen von ihnen? Ich möchte dem Benutzer erlauben, aus einem Drop-Down-Menü einen Trainer auszuwählen und dann die ID dieses Trainers auf das Feld Trainer_ID zu setzen. –

Verwandte Themen