2015-11-03 70 views
10

我有一堆'孩子'對象已保存,我想創建一個父對象,通過'相對'模型鏈接到孩子。如何從父控制器保存我的子記錄?

這個對象給我一個多對多,通過親戚。

要清楚:用戶訪問'父母'頁面,點擊創建父母,並顯示一個表單,讓他們命名父母,併爲此父母添加四個孩子(通過創建'親屬'),每個這些'關係'也被命名 - 這是一個重要的部分。因此,例如,我可以命名關係「步子」或「兒子」。

這裏是我到目前爲止的代碼:

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 

當我的父母控制器「創造」,我可以看到正確的參數被打通,但關係記錄不被保存。這不應該自動發生?

我試過循環遍歷:relatives_attributes,但似乎沒有與'build'一起使用。

我如何獲得「親屬」記錄以保存?

編輯:添加參數發佈:

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"}}} 

編輯:我已經更新這表明我的最新編輯 - 注意 'parent_params [:relatives_attributes]。每做| K,R |'在控制器中。這現在保存孩子的記錄,但唯一的問題是,它也保存空白的字段!所以我有'親戚'記錄與孩子記錄空值。我怎樣才能阻止它保存空字段(或創建空的相對記錄)?

+0

請刪除創建操作中的'parent_params [:relatives_attributes] .each ...'東西。之後,檢查控制檯是否在保存時出現「COMMIT」或「ROLLBACK」。如果你有一個回滾,只需在呈現錯誤之前添加'puts @ parent.errors.full_messages.inspect'並檢查控制檯。如果你有一個提交檢查你的控制檯「未經許可的屬性」(但我認爲它是正確的,你不會發現這一點)。 –

+0

它提交。控制檯上沒有未經許可的參數警告。但是,它不會將親戚保存在父母身上(我在軌道控制檯中查看了記錄)。 –

+0

噢,我讀了標題'如何從父控制器保存我的子記錄?'並且認爲這是來自另一個家長在學校或幼兒園詢問孩子記錄的堆棧交換網站! –

回答

3

答案是建立相對每個子記錄,就像這樣:

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

在調用@ parent.save之前。

但是,我仍然有問題擺脫空白記錄。所以如果任何人對這個問題有一個答案,請在這裏發表評論 - 或者如果有更好或更傳統的做法,請打我。後續跟進問題:Why is this reject_if in my model not rejecting blank records?

2

你幾乎沒有,這取決於您的表單提交如何,你很可能需要在相對關聯類的accepts_nested_attribute_for還有:

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

如果這不起作用,那麼請提交您的被傳遞到控制器,我們可以調整相應PARAMS

+0

就像我說過的,我已經有一堆已經保存的'孩子'對象' - 所以我不需要在Relative上爲孩子添加accept_nested。我在父母控制器中創建了Relative,所以我不需要爲父母接受任何東西 - 它以相反的方式工作(親戚的數據包含在父母控制器的帖子中,嵌套)。我將在上面的問題中添加發布到控制器的參數。謝謝。 –

+0

雖然要徹底,但我確實嘗試過,並沒有改變任何東西。沒有任何'孩子'記錄得到保存。請注意,在上面的例子中,只有一個孩子正在爲父母填寫。這是故意的 - 它應該忽略空白。 –