简体   繁体   English

如何从父控制器保存子记录?

[英]How do I save my child records from the parent controller?

I have a bunch of 'kid' objects saved already and I want to create a parent object which is linked to the kids via a 'relative' model. 我已经保存了一堆“孩子”对象,我想创建一个父对象,该对象通过“相对”模型链接到孩子。

This object gives me a many-to-many, through relatives. 这个对象通过亲戚给了我很多对很多。

To be clear: the user visits the 'parents' page, clicks create parents and is presented with a form that lets them name the parent and add up to four children to this parent (by creating 'relatives'), each of these 'relations' is also named - that's an important part. 明确说明:用户访问“父母”页面,单击“创建父母”,并显示一个表单,该表单可让他们命名父母并为该父母添加最多四个孩子(通过创建“亲戚”),每个“亲戚” ”也被命名-这是重要的部分。 So, I could name the relation 'step son' or 'son', for instance. 因此,例如,我可以将关系命名为“继子”或“儿子”。

Here's the code I have so far: 这是我到目前为止的代码:

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

When I get to 'create' in the parents controller, I can see the right parameters are getting through but the relationship records aren't being saved. 当我在父控制器中进行“创建”时,可以看到正确的参数通过了,但是关系记录没有保存。 SHouldn't this happen automatically? 这不是应该自动发生吗?

I've tried looping through the :relatives_attributes but that doesn't seem to work with 'build'. 我尝试遍历:relatives_attributes,但是似乎不适用于'build'。

How am I suppsed to get the 'relatives' records to save? 我该如何保存“亲戚”记录以保存?

EDIT: adding parameters posted: 编辑:添加参数发布:

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: I've updated this to show my latest edit - note the 'parent_params[:relatives_attributes].each do |k,r|' 编辑:我已经更新了它以显示我的最新编辑-请注意'parent_params [:relatives_attributes] .each do | k,r |' in the controller. 在控制器中。 This now saves the kid records but the only problem is, it also saves the fields that are blank! 现在可以保存孩子的记录,但是唯一的问题是,它还可以保存空白的字段! So I have 'relative' records with null values for kid records. 所以我有孩子记录的空值的“相对”记录。 How can I stop it saving empty fields (or creating empty relative records)? 如何停止保存空白字段(或创建空白的相对记录)?

The answer was to build each sub-record of relative, like so: 答案是建立相对的每个子记录,如下所示:

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

Before calling @parent.save. 在调用@ parent.save之前。

However, I'm still having issues getting rid of the blank records. 但是,我仍然有摆脱空白记录的问题。 So if anyone has an answer to that problem, please comment here - or if there's a better or more traditional way of doing this, hit me up. 因此,如果有人对这个问题有答案,请在这里评论-或如果有更好或更传统的方式来解决这个问题,请打我。 Follow up question here: Why is this reject_if in my model not rejecting blank records? 在此跟进问题: 为什么我的模型中的这个reject_if不拒绝空白记录?

You are almost there, depending upon how your form submission is, you most likely need an accepts_nested_attribute_for in your Relative associative class as well: 您几乎就在那儿,具体取决于表单提交的方式,您最有可能在您的相对关联类中也需要一个accepts_nested_attribute_for:

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

If this doesn't work, then please submit your params that are passed into the controller and we can adjust accordingly 如果这不起作用,那么请提交您传递给控制器​​的参数,我们可以相应地进行调整

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM