【问题标题】:Rails 5 - form_with - fields_for assign nested attributes upon creation of parent items.Rails 5 - form_with - fields_for 在创建父项时分配嵌套属性。
【发布时间】:2018-12-13 15:44:32
【问题描述】:

我是 Rails 或一般编码的新手,试图通过创建一个简单的应用程序来学习,我不确定问这个问题是否愚蠢,但我尝试真正找到问题的具体答案,但每次都失败了天,如果有人可以帮助我,我将不胜感激;

我有一个“Plane”模型,它具有“PlaneModel”、“Xroutes”和“Staffs”属性。每 3 个属性都是预先创建的,有自己的表,并且在创建平面的新实例时,您只需通过“collection_select”选择可用项目。 Plane.rb 的代码;

class Plane < ApplicationRecord
  belongs_to :plane_model
  belongs_to :xroute    
  has_many :staffs
  accepts_nested_attributes_for :staffs
end

现在,由于 db 关系,Planes 表有一个 Planemodel_id、Xroute_id 但没有 Staff_id。这就是问题所在,因为当我尝试创建平面实例时,“collection_select”很容易适用于前 2 个属性,分别分配 Planemodel_id 和 Xroute_id。对于员工,虽然我想要实现的是,在创建每个平面后,在员工表中的相应员工行上分配该 plane_id。 Staff.rb 的代码;

class Staff < ApplicationRecord
  belongs_to :hub, optional: true
  belongs_to :plane, optional: true
end

下面是飞机的_form;

<%= form_with(model: plane, local: true) do |form| %>
  <div class="control-group">
    <%= form.label :plane_model_id %>
    <div class="controls">
      <%= collection_select( :plane, :plane_model_id, PlaneModel.all, :id, :name, {}, { :multiple => false } ) %>
    </div>
  </div>

  <div class="control-group">
    <%= form.label :xroute_id %>
    <div class="controls">
      <%= collection_select( :plane, :xroute_id, Xroute.all, :id, :name, {}, { :multiple => false } ) %>
    </div>
  </div>

  <%= form.fields_for :staffs do |staff| %>
    <div class="control-group">
      <%= staff.label :staff_id %>
      <div class="controls">
        <%= staff.collection_select( :plane_id, Staff.all, :id, :name, { :multiple => false } ) %>
      </div>
    </div>
  <% end %>

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

在平面控制器内部新建和创建函数和参数函数以将属性列入白名单;

def new
  @plane = Plane.new
  3.times { @plane.staffs.build }
end

def create
  @plane = Plane.new(plane_params)    
  respond_to do |format|
    if @plane.save
      format.html { redirect_to @plane, notice: 'Plane was successfully created.' }
      format.json { render :show, status: :created, location: @plane }
    else
      format.html { render :new }
      format.json { render json: @plane.errors, status: :unprocessable_entity }
    end
  end
end

def plane_params
  params.require(:plane).permit(:plane_model_id, :xroute_id, staffs_attributes: [:id, :staff, :plane_id])
end

这是正在发生的事情的可视化表示;

Form for creating new plane instance, PlaneModel, Xroute and 3 staff members are selected from dropdown lists.

When submitted, a new instance is successfully created.

Here is the index page for Planes, as you see PlaneModel and Xroute are there.

但是,当我转到人员页面时,不是将创建的飞机的 id 放在选定的人员“plane_id”字段中,而是抛出额外的 3 个人员实例,而没有任何更多信息。

Staff index page showing, newly created empty staff instances.

就像我说的那样,这可能是一件简单的事情,但我肯定错过了一些东西,感谢所有帮助和建议。

谢谢,

【问题讨论】:

    标签: ruby-on-rails nested-attributes fields-for


    【解决方案1】:

    accepts_nested_attributes_for :staffs 允许您在同一个表单内创建一个人员实例和一个平面。但正如我所见,您只想选择现有员工,对吗?你需要改变你的形式:

    <div class="control-group">
      <%= form.label :staff_ids %>
      <div class="controls">
        <%= form.collection_select( :staff_ids, Staff.all, :id, :name, {}, { multiple: true } ) %>
      </div>
    </div>
    

    参数:

    def plane_params
      params.require(:plane).permit(:plane_model_id, :xroute_id, staff_ids: [])
    end
    

    并从新操作中删除 3.times { @plane.staffs.build }

    【讨论】:

    • 感谢您的回答,通过“staff_ids: []”它在控制台中返回一个未经许可的参数,当我尝试“:staff_ids”时,它可以工作,但它只接受一个值。有没有办法让这个许可数组工作?
    • 我找到了方法,将collection_select改为如下; true } ) %> 这使得“staff_ids[]”工作并允许多选。非常感谢!
    • @MelihAlan,对不起,错过了空白选项哈希。我已经更新了答案,如果有帮助请采纳
    • 当然可以,我不知道我应该接受,现在全部完成,再次感谢。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-04-23
    • 2012-07-08
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多