2010-10-14 4 views
6

Non sono esattamente sicuro di quello che il mio problema è, quindi questa domanda può richiedere un po 'di chiarimento, ma ecco quello che sembra essere più rilevanti:rotaie 3 has_many: attraverso record di salvare errore

Ho un has_many :through e la join model ha alcuni campi che non sono chiavi esterne. Quando costruisco i modelli e provo a salvare, viene visualizzato un errore di convalida sui campi chiave non esterni del modello di join.

miei file assomigliano:

Person.rb 

    has_many :wedding_assignments, :dependent => :destroy 
    has_many :weddings, :through=>:wedding_assignments 
    accepts_nested_attributes_for :weddings 
    accepts_nested_attributes_for :wedding_assignments 

Wedding.rb 

    has_many :wedding_assignments, :dependent => :destroy 
    has_many :people, :through=>:wedding_assignments 
    accepts_nested_attributes_for :people 
    accepts_nested_attributes_for :wedding_assignments 

WeddingAssignment.rb 

    belongs_to :person 
    belongs_to :wedding 
    validates_presence_of :role, :person, :wedding 

(ruolo è una stringa)

people_controller.rb 

    def new 
    @person = Person.new 

    1.times do 
     wedding = @person.weddings.build 
     1.times do 
     assignment = wedding.wedding_assignments.build 
     assignment.person = @person 
     assignment.wedding = wedding 
     end 
    end 
    end 

    def create 
    @person = Person.new(params[:person]) 
    @person.weddings.each do |wedding| 
     wedding.wedding_assignments.each do |assignment| 
     assignment.person = @person #i don't think I should need to set person and wedding manually, but I get a validation error if I don't 
     assignment.wedding = wedding 
     end 
    end 
end 

i params che tornano assomigliano:

{"first_name"=>"", "last_name"=>"", "weddings_attributes"=>{"0"=>{"wedding_assignments_attributes"=>{"0"=>{"role"=>"Bride's Maid", "budget"=>""}}, "date"=>"", "ceremony_notes"=>""}}} 

E l'errore esatto è:

ActiveRecord::RecordInvalid in PeopleController#create 
Validation failed: Role can't be blank 

Il che chiaramente non è corretto, dal momento che si può vedere in params[]

Che cosa sto facendo di sbagliato?

Questo è rotaie 3.0.0

+2

Sono curioso che cosa è l'uso di quei '1.times'? – PeterWong

+0

Lo faccio per renderlo facile se voglio cambiarlo a 2.times o più tardi. – SooDesuNe

+0

Hai ragione, farlo può anche consentire all'utente di scegliere l'aggiunta di 10 matrimoni in una volta. : D – PeterWong

risposta

0

provare a cambiare "Person.new" a "Person.create", forse creando il record nel db subito aiuterà con le associazioni.

+0

Io sicuramente non li voglio nel database subito. Cosa succede se l'utente cambia idea e si allontana dalla pagina? Non avrò un record vuoto se utilizzo 'create'? – SooDesuNe

1

destro, questo è un po 'di una supposizione, quindi mi scuso se mi vento fino sprecare il vostro tempo qui ...

Sembra a me come nel vostro metodo create, si sta creando il rapporto 'matrimonio' (che è solo una relazione "finta" in realtà, ha utilizzato: through =>: wedding_assignments), e quindi restituire questo. Stai quindi chiedendo ai binari di ricreare questi oggetti nella tua chiamata a Person.new. La mia ipotesi è che le rotaie si confondano cercando di creare un oggetto sul lato estremo di un has_many: through senza che l'oggetto intermedio sia presente.

sarei tentato di ristrutturare questo un po '(codice non testato!):

def new 
    @person = Person.new 
    @wedding = Wedding.new 
    @wedding_assignment = WeddingAssignment.new 
end 

def create 
    @person = Person.new(params[:person]) 
    @wedding = Wedding.new(params[:person]) 
    @assignment = WeddingAssignment.new(params[:wedding_assignment].merge({:person => @person})) 
end 

Ho la sensazione che questo sarà il lavoro fino a quando l'ultima riga. Ho il sospetto per ottenere che al lavoro potrebbe essere necessario utilizzare le transazioni:

def create 
    @person = Person.new(params[:person]) 
    @wedding = Wedding.new(params[:person]) 
    ActiveRecord::Base.transaction do 
    if @person.valid? && @wedding.valid? 
     [@person,@wedding].each.save! 
     @assignment = WeddingAssignment.new(params[:wedding_assignment].merge({:person => @person})) 
     @assignment.save! 
    end 
    end 
end 

Questo dovrebbe garantire che tutto è stato creato nel giusto ordine e ID sono disponibili al momento giusto, ecc Purtroppo, però, è un po 'più complicato del tuo esempio e significa che lotterai per sostenere più matrimoni.

Spero che questo aiuti, e non finisce per essere un vicolo cieco.

+0

Di gran lunga la migliore risposta ancora. Farlo in questo modo significa che non sarò in grado di generare i campi del modulo in modo pulito (ad esempio in: http://railscasts.com/episodes/196-nested-model-form-part-1). I binari dovrebbero essere in grado di gestire queste associazioni. Durante il fine settimana ho riscritto il codice per creare ed eseguire a partire dal modello di join, WeddingAssignment, anziché da Person, e funziona perfettamente. Quindi penso che tu sia sulla strada giusta perché i binari si confondano ' – SooDesuNe

+0

Ho un problema simile che sto cercando di risolvere con questa domanda, ma sto ricevendo un errore di sicurezza di massa di persona. Qualche idea? – ctilley79