2015-11-03 18 views
10

Ho già un gruppo di oggetti "bambini" che sono già stati salvati e voglio creare un oggetto padre collegato ai bambini tramite un modello "relativo".Come posso salvare i miei record figli dal controller principale?

Questo oggetto mi dà un molti-a-molti, attraverso parenti.

Per essere chiari: l'utente visita la pagina "genitori", i clic creano genitori e viene presentato con un modulo che consente loro di nominare il genitore e di aggiungere fino a quattro figli a questo genitore (creando "parenti"), ciascuno di queste "relazioni" è anche chiamato - questa è una parte importante. Quindi, potrei nominare la relazione "figliastra" o "figlio", per esempio.

Ecco il codice che ho finora:

class Kid < ActiveRecord::Base 
    has_many :relatives 
    has_many :parents, through: :relatives 
end 


class Parent < ActiveRecord::Base 
    has_many :relatives 
    has_many :kids, through: :relatives 

    accepts_nested_attributes_for :relatives, 
    :reject_if => lambda { |a| a[:content].blank? }, 
    :allow_destroy => true 
end 


class Relative < ActiveRecord::Base 
    belongs_to :parent 
    belongs_to :kid 
end 



class ParentsController < ApplicationController 
    before_action :set_parent, only: [:show, :edit, :update, :destroy] 
    before_action :lookup_kids, only: [:new, :edit] 

    # GET /parents 
    # GET /parents.json 
    def index 
    @parents = Parent.all 
    end 

    # GET /parents/1 
    # GET /parents/1.json 
    def show 
    end 

    # GET /parents/new 
    def new  
    @parent = Parent.new 
    4.times { @parent.relatives.build } 
    end 

    # GET /parents/1/edit 
    def edit 
    end 

    # POST /parents 
    # POST /parents.json 
    def create 
    @parent = Parent.new(parent_params)   

    parent_params[:relatives_attributes].each do |k,r| 
     @parent.relatives.build(r.except(:_destroy)) 
    end 

    respond_to do |format| 
     if @parent.save 
     format.html { redirect_to @parent, notice: 'Parent was successfully created.' } 
     format.json { render :show, status: :created, location: @parent } 
     else 
     format.html { render :new } 
     format.json { render json: @parent.errors, status: :unprocessable_entity } 
     end 
    end 
    end 

    # cut for brevity. 



    private 

    # Use callbacks to share common setup or constraints between actions. 
    def set_parent 
     @parent = Parent.find(params[:id]) 
    end 


    def parent_params 
     params.require(:parent).permit(:name, 
     relatives_attributes: [:parent_id, :kid_id, :relationship, :_destroy]) 
    end 
    def lookup_kids 
     @kids = Kid.all #for this nursery. 
    end 
end 





<%= form_for(@parent) do |f| %> 
    <% if @parent.errors.any? %> 
    <div id="error_explanation"> 
     <h2><%= pluralize(@parent.errors.count, "error") %> prohibited this parent from being saved:</h2> 
     <ul> 

     <% @parent.errors.full_messages.each do |message| %> 
     <li><%= message %></li> 
     <% end %> 
     </ul> 
    </div> 
    <% end %> 

    <div class="field"> 
    <%= f.label :name %><br> 
    <%= f.text_field :name %> 
    </div> 

    <h4>Kids:</h4> 
    <%= f.fields_for :relatives do |r| %> 
    <%= r.label :kid %> 
    <%= r.collection_select :kid_id, 
     @kids, :id, :name, include_blank: true%> 
    <%= r.label :relationship %> 
    <%= r.text_field :relationship %>  
    <%= r.check_box :_destroy %> 
    <%= r.label :_destroy, "Remove" %> 
    <br/> 
    <% end %> 

    <div class="actions"> 
    <%= f.submit %> 
    </div> 
<% end %> 



ActiveRecord::Schema.define(version: 20151030113634) do 
    create_table "kids", force: :cascade do |t| 
    t.string "name" 
    t.datetime "created_at", null: false 
    t.datetime "updated_at", null: false 
    end 
    create_table "parents", force: :cascade do |t| 
    t.string "name" 
    t.datetime "created_at", null: false 
    t.datetime "updated_at", null: false 
    end 
    create_table "relatives", force: :cascade do |t| 
    t.string "relationship" 
    t.integer "parent_id" 
    t.integer "kid_id" 
    t.datetime "created_at", null: false 
    t.datetime "updated_at", null: false 
    end 
    add_index "relatives", ["kid_id"], name: "index_relatives_on_kid_id" 
    add_index "relatives", ["parent_id"], name: "index_relatives_on_parent_id" 
end 

Quando arrivo a 'creare' nel controller genitori, posso vedere i giusti parametri sono sempre attraverso ma i record di relazione non vengono salvate. Non dovrebbe accadere automaticamente?

Ho provato a eseguire il looping di: relatives_attributes ma non sembra funzionare con "build".

Come si suppone per ottenere i record dei "familiari" da salvare?

EDIT: aggiunta di parametri pubblicati:

parent"=>{ 
    "name"=>"Dad", 
    "relatives_attributes"=>{ 
    "0"=>{"kid_id"=>"2", "relationship"=>"Son", "_destroy"=>"0"}, 
    "1"=>{"kid_id"=>"", "relationship"=>"", "_destroy"=>"0"}, 
    "2"=>{"kid_id"=>"", "relationship"=>"", "_destroy"=>"0"}, 
    "3"=>{"kid_id"=>"", "relationship"=>"", "_destroy"=>"0"}}} 

Edit: Ho aggiornato questo per mostrare la mia ultima modifica - notare il 'parent_params [:] relatives_attributes .each fare | k, r |' nel controller. Questo ora salva i record del bambino ma l'unico problema è che salva anche i campi che sono vuoti! Quindi ho i record "relativi" con valori nulli per i record figli. Come posso smettere di salvare campi vuoti (o creare record relativi vuoti)?

+0

Rimuovere gli elementi 'parent_params [: relatives_attributes] .each ...' dall'azione di creazione. Dopodiché controlla la console se ottieni un 'COMMIT' o un' ROLLBACK' al salvataggio. Se hai avuto un rollback, aggiungi 'puts @ parent.errors.full_messages.inspect' prima di eseguire il rendering dell'errore e controlla la console. Se avevi un commit controlla la tua console per gli attributi 'non permessi '(ma penso che sia giusto e non lo avrai trovato). –

+0

Si impegna. Non ci sono avvertimenti sui parametri non autorizzati sulla console. Tuttavia, non salva i "parenti" sul genitore (ho controllato il record nella console delle rotaie). –

+0

D'oh ho letto il titolo 'Come faccio a salvare i miei record figli dal controller principale?'e ho pensato che fosse da un altro sito di scambio di oggetti in cui un genitore sta chiedendo dei registri dei loro figli a scuola o all'asilo! –

risposta

3

la risposta era di costruire ogni sotto-record di relativo, in questo modo:

parent_params[:relatives_attributes].each do |k,r| 
    @parent.relatives.build(r.except(:_destroy)) 
end 

Prima di chiamare @ parent.save.

Tuttavia, ho ancora problemi a eliminare i record vuoti. Quindi se qualcuno ha una risposta a questo problema, per favore commenta qui - o se c'è un modo migliore o più tradizionale per farlo, fammi un colpetto. Domanda successiva: Why is this reject_if in my model not rejecting blank records?

2

siete quasi arrivati, a seconda di come vostro modulo di presentazione è, molto probabilmente bisogno di un accepts_nested_attribute_for nella classe associativa relativa così:

class Relative 
    belongs_to :parent 
    accepts_nested_attributes_for :parent 
    belongs_to :kid 
    accepts_nested_attributes_for :kid 
end 

Se questo non funziona, quindi si prega di inviare la tua params che sono passati nel controller e siamo in grado di regolare di conseguenza

+0

Come ho già detto, ho già un gruppo di oggetti "bambini" già salvati ", quindi non ho bisogno di aggiungere accept_nested per kid su Relative. Sto creando il Relative all'interno del controller genitori, quindi non ho bisogno di accept_nested per il genitore o - viceversa (i dati relativi sono inclusi nel post al controller genitori, nidificati). Aggiungerò i parametri inviati al controller nella domanda sopra. Grazie. –

+0

Per essere esauriente, ho provato questo e non ha cambiato nulla. Nessuno dei record "bambini" è stato salvato. Nota nell'esempio sopra, solo un bambino viene compilato per il genitore. Questo è intenzionale - dovrebbe ignorare gli spazi vuoti. –

Problemi correlati