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

Ruby on rails 如何从父控制器保存子记录?,ruby-on-rails,Ruby On Rails,我已经保存了一堆“孩子”对象,我想创建一个通过“相对”模型链接到孩子的父对象 这个物体通过亲戚给了我很多很多 需要明确的是:用户访问“家长”页面,单击“创建家长”,并显示一个表单,允许他们命名家长,并将最多四个孩子添加到此家长(通过创建“亲属”),每个“关系”也被命名,这是一个重要部分。例如,我可以将这种关系命名为“继子”或“子” 以下是我目前掌握的代码: class Kid < ActiveRecord::Base has_many :relatives has_many :pa

我已经保存了一堆“孩子”对象,我想创建一个通过“相对”模型链接到孩子的父对象

这个物体通过亲戚给了我很多很多

需要明确的是:用户访问“家长”页面,单击“创建家长”,并显示一个表单,允许他们命名家长,并将最多四个孩子添加到此家长(通过创建“亲属”),每个“关系”也被命名,这是一个重要部分。例如,我可以将这种关系命名为“继子”或“子”

以下是我目前掌握的代码:

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

Edit:我已更新此项以显示我的最新编辑-请注意“parent_params[:relatives_attributes]。控制器中的每个do | k,r |”。这现在保存了kid记录,但唯一的问题是,它还保存了空白字段!所以我有“相对”记录,其中kid记录的值为空。如何停止保存空字段(或创建空的相对记录)?

根据表单提交的方式,您很可能还需要相对关联类中的accepts_nested_属性:

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

如果这不起作用,那么请提交传递到控制器中的参数,我们可以相应地调整

答案是构建relative的每个子记录,如下所示:

parent_params[:relatives_attributes].each do |k,r|
  @parent.relatives.build(r.except(:_destroy))
end
在呼叫@parent.save之前


但是,我仍然有摆脱空白记录的问题。因此,如果有人对这个问题有答案,请在这里发表评论——或者如果有更好或更传统的方法,请联系我。接下来的问题是:

正如我所说,我已经保存了一堆“kid”对象,所以我不需要在Relative上为kid添加嵌套的accepts\u。我正在parents控制器中创建Relative,因此我也不需要为parents嵌套—它的工作方式正好相反(post to parents控制器中包含的Relative数据,嵌套)。我将在上面的问题中添加发布到控制器的参数。谢谢。不过为了彻底起见,我确实试过这个,但它没有改变任何东西。“孩子”的记录都没有保存。注意,在上面的例子中,只有一个孩子被填写为家长。这是故意的-它应该忽略空格。请从创建操作中删除父参数[:亲戚属性]。每个…内容。之后,如果保存时收到
COMMIT
ROLLBACK
,请检查控制台。如果有回滚,只需添加
put@parent.errors.full_消息。在呈现错误之前检查
,并检查控制台。如果您有提交功能,请检查控制台中是否有未经许可的属性(但我认为这是正确的,您将找不到)。它会提交。控制台上没有未经允许的参数警告。但是,它不会在家长上保存“亲属”(我在rails控制台中查看了记录)。哦,我读了标题
如何从家长控制器保存我的孩子记录?
,并认为这是从另一个stackexchange站点发来的,在那里,家长正在询问他们孩子在学校或幼儿园的记录!
parent_params[:relatives_attributes].each do |k,r|
  @parent.relatives.build(r.except(:_destroy))
end