首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Rails 4嵌套表单,包括has_many、Rails和multiple

Rails 4嵌套表单,包括has_many、Rails和multiple
EN

Stack Overflow用户
提问于 2016-07-24 22:09:51
回答 2查看 3K关注 0票数 3

嵌套表单和has_many关系存在问题。商业案例:有实验室和他们的供应商。供应商可以在实验室之间共享。

模型

代码语言:javascript
复制
class Lab < ActiveRecord::Base
  has_many :lab_suppliers
  has_many :suppliers, through: :lab_suppliers
  accepts_nested_attributes_for :lab_suppliers
end

class Supplier < ActiveRecord::Base
  has_many :lab_suppliers
  has_many :labs, through: :lab_suppliers
  accepts_nested_attributes_for :lab_suppliers
end

class LabSupplier < ActiveRecord::Base
  belongs_to :lab
  belongs_to :supplier

  accepts_nested_attributes_for :lab
  accepts_nested_attributes_for :supplier
end

表单

代码语言:javascript
复制
<%= form_for(@lab) do |f| %>
  <div class="field">
    <%= f.label :code %><br>
    <%= f.text_field :code %>
  </div>
  <div class="field">
    <%= f.label :name %><br>
    <%= f.text_field :name %>
  </div>
  <div class"field">
    <%= fields_for :lab_suppliers do |ff| %>
      <%= ff.label :supplier_id %><br>
      <%= ff.collection_select :supplier_id, Supplier.all, :id, :name,  {include_blank: true}, {:multiple => true, :class=>""} %> 
    <% end %>
  </div>
  <div class="actions">
    <%= f.submit %>
  </div>
<% end %>

控制器

代码语言:javascript
复制
class LabsController < ApplicationController
  before_action :set_lab, only: [:show, :edit, :update, :destroy]

  # GET /labs/new
  def new
    @lab = Lab.new
    @lab.lab_suppliers.build
  end

  # POST /labs
  # POST /labs.json
  def create
    #raise params.inspect

    @lab = Lab.new(lab_params)

    @lab_supplier = @lab.lab_suppliers.new(params[:lab_suppliers])
    @lab_supplier.save
    @lab.save


    private

    def lab_params
      params.require(:lab).permit(:code, :name, lab_suppliers_attributes: [])
    end
end

提交表格后对对撞机进行检查的结果:

参数:

代码语言:javascript
复制
{"utf8"=>"✓",
 "authenticity_token"=>"...",
 "lab"=>{"code"=>"L01",
 "name"=>"xxx"},
 "lab_suppliers"=>{"supplier_id"=>["",
 "1",
 "3"]},
 "commit"=>"Create Lab"}

在提交表单时,我在行中接收ActiveModel::ForbiddenAttributesError:

代码语言:javascript
复制
@lab_supplier = @lab.lab_suppliers.new(params[:lab_suppliers])

我错过了什么让它像预期的那样运作?

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2016-07-24 22:31:48

您似乎需要显式地告诉lab_params您需要从lab_suppliers传递哪些属性,例如:

代码语言:javascript
复制
params.require(:lab).permit(:code, :name, lab_suppliers_attributes: [:supplier_id])

试着让我知道。

票数 2
EN

Stack Overflow用户

发布于 2016-07-26 10:35:45

链接到帮助我找到工作解决方案的其他帖子:[带有多个entries](https://stackoverflow.com/questions/14576277/rails-nested-form-with-multiple-entries)的Rails嵌套表单

下面我提供了一个工作解决方案,演示如何将多个select的值作为嵌套属性传递并插入到db。

模型

代码语言:javascript
复制
class Lab < ActiveRecord::Base
   has_many :lab_suppliers#, :foreign_key => 'lab_id', dependent: :destroy
   has_many :suppliers, through: :lab_suppliers
   accepts_nested_attributes_for :lab_suppliers, :allow_destroy => true
end

class Supplier < ActiveRecord::Base
  has_many :lab_suppliers
  has_many :labs, through: :lab_suppliers
end

class LabSupplier < ActiveRecord::Base
  belongs_to :lab
  belongs_to :supplier
end

注释: accepts_nested_attributes_for只放在has/has_一面。不需要把它放在belongs_to上

表格(实验室)

代码语言:javascript
复制
<%= form_for(@lab) do |f| %>
  <div class="field">
    <%= f.label :code %><br>
    <%= f.text_field :code %>
  </div>
  <div class="field">
    <%= f.label :name %><br>
    <%= f.text_field :name %>
  </div>
    <div class"field">
<%= f.fields_for :lab_suppliers do |ff| %>
  <%= ff.label :supplier_id %><br>
  <%= ff.collection_select :supplier_id, Supplier.all, :id, :name,  {include_blank: true}, {:multiple => true, :class=>""} %>
<% end %>

<%= f.submit %><% end %>

控制器

注释:没有必要允许在供应商或lab_suppliers控制器中增加任何参数。

代码语言:javascript
复制
class LabsController < ApplicationController
  before_action :set_lab, only: [:show, :edit, :update, :destroy]

def new
  @lab = Lab.new
  @lab.lab_suppliers.build
end


def create
   @lab = Lab.new(lab_params)

@startcount=1   #start counting from 1 because the first element in the array of nested params is always null
@lab.lab_suppliers.each do |m|
  #raise lab_params[:lab_suppliers_attributes]["0"][:supplier_id][@startcount].inspect
  m.supplier_id = lab_params[:lab_suppliers_attributes]["0"][:supplier_id][@startcount]
  @startcount +=1
end 

respond_to do |format|
  if @lab.save
    lab_params[:lab_suppliers_attributes]["0"][:supplier_id].drop(@startcount).each do |m|
      @lab.lab_suppliers.build(:supplier_id => lab_params[:lab_suppliers_attributes]["0"][:supplier_id][@startcount]).save
      @startcount += 1
    end
    format.html { redirect_to labs_path, notice: 'Lab was successfully created.' }
    format.json { render :show, status: :created, location: @lab }
  else
    format.html { render :new }
    format.json { render json: @lab.errors, status: :unprocessable_entity }
  end
end
end


    private

def lab_params
  params.require(:lab).permit(:name, :code, lab_suppliers_attributes: [supplier_id: [] ])
end
end

注释: supplier_id:[]在要传递的多个下拉列表中的lab_suppliers_attributes permitts数组中

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/38557320

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档