2010-08-03 6 views
9

È possibile che un modello appartenga a, due modelli e abbia una relazione nidificata?può modellare "belong_to" altri due modelli e avere una relazione nidificata?

cioè di ciò che voglio

class trainer 
has_many :appointments 
end 

class appointment 
belong_to :trainer, :customer 
end 

class customer 
has_many :appointments 
end 

al momento ho solo i modelli dei clienti e degli appuntamenti che sono annidati per esempio di quello che ho:

creare metodo assomiglia a questo:

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 percorsi che ho:

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

è possibile avere 2 relazioni annidate per 1 modello? a cosa dovrei cambiare il metodo di creazione, se l'appuntamento fosse anche di un formatore o di un cliente?

grazie

risposta

19

Supponendo che si sta utilizzando ActiveRecord: Avere un modello appartengono a più di un altro modello è possibile, naturalmente, (tuttavia è necessario specificare una dichiarazione belongs_to per ogni relazione).

class Appointment < ActiveRecord::Base 
    belongs_to :trainer 
    belongs_to :customer 
end 

Un rapporto di appartenenza non significa necessariamente che il record abbia effettivamente quell'altro record correlato; può anche essere nulla. Quindi puoi avere appuntamenti che appartengono ad un allenatore ma nessun cliente e viceversa.

In realtà non si può nemmeno avere né un trainer né un cliente o un trainer e un cliente in questo modo - se questo viola la propria logica aziendale, si potrebbe voler aggiungere una convalida per evitare ciò.

Il metodo di creazione del controller esistente deve continuare a funzionare come è, è sufficiente aggiungere la gestione dei record del trainer. Puoi persino utilizzare lo stesso controller per gestire la nomina di istruttori e clienti estraendo istruttori e clienti, ad es. in una persona come questo:

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 

In questo modo, è possibile utilizzare lo stesso AppointmentsController per entrambi i percorsi

# 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 

Naturalmente, questo ha senso solo se la logica e la vista dietro appuntamenti allenatore e gli appuntamenti dei clienti sono quasi la stessa cosa In caso contrario, è possibile utilizzare diversi controller

# 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 risposta! grazie. solo una domanda, se creo l'appuntamento dalla pagina/vista del cliente. come posso aggiungere l'ID trainer all'appuntamento? posso caricare tutti i trainer nella vista e consentire all'utente di selezionare un trainer dal menu a discesa, quindi assegnare l'ID del trainer al trainer_id archiviato nell'appuntamento? –

+0

La tua domanda sul param trainer_id o sull'attributo record? Il parametro trainer_id viene impostato dalla rotta di risorsa nidificata. '/ trainers/123/appointments' imposta' params [: trainer_id] 'su 123,'/customers/123/appointments' imposta 'params [: customer_id]' su 123. L'attributo trainer_id sul record degli appuntamenti viene impostato da has_many associazione. '@appointment = person.appointments.build' imposterà automaticamente' @ appointment.trainer_id' o '@ appointment.customer_id' a' person.id' a seconda di quale classe è (per cambiare i valori di default, c'è un'opzione: foreign_key per appartiene a). – Zargony

+0

consente di passare a un profilo cliente e creare un appuntamento dal suo profilo (raccoglierà l'id dai parametri customer_id), ma come faccio a assegnare a quell'appuntamento un trainer che si occuperà di tale appuntamento. se ho 10 istruttori, come posso fissare l'appuntamento a uno di loro? voglio consentire all'utente di scegliere da un menu a discesa un trainer e quindi impostare l'ID di quel trainer nel campo trainer_id? –

Problemi correlati