Rails 编辑嵌套表单时创建重复项
Rails creating duplicates when editing nested form
我进行了很多谷歌搜索,然后全部返回到将 :id 添加到允许的属性,但这在我的情况下不起作用,所以:
在编辑嵌套表单时如何防止创建多个空行(在相关表中)?
每次我编辑一个表格,它都会使空相关记录的数量增加一倍。
控制器:
class EnquiriesController < ApplicationController
before_action :authenticate_user!
load_and_authorize_resource
# before_action :set_enquiry, only: [:show, :edit, :update, :destroy]
#11-1-2017 Devise geinstalleerd, nog verder afmaken!(oa onderstaande uncommenten)
# GET /enquiries
# GET /enquiries.json
def index
# @enquiries = Enquiry.all
@enquirie = current_user.enquiries
end
# GET /enquiries/1
# GET /enquiries/1.json
def show
end
# GET /enquiries/new
def new
@enquiry = Enquiry.new
@enquiry.enquirymeasures.build
#@enquiry.measurements.build
@enquiry.tools.build
@enquiry.build_applicant
@enquiry.signatures.build
@enquiry.gasmeters.build
#@enquiry.enquirymeasures.build.build_measurement
end
# GET /enquiries/1/edit
def edit
#nog op kunnen slaan!!!! 1-01-17 Marco
@enquiry = Enquiry.find(params[:id])
@enquiry.enquirymeasures.build
@enquiry.tools.build
@enquiry.build_applicant
@enquiry.signatures.build
@enquiry.gasmeters.build
end
# POST /enquiries
# POST /enquiries.json
def create
@enquiry.user_id = current_user.id
@enquiry = Enquiry.new(enquiry_params)
#@enquiry.enquirymeasures.build
respond_to do |format|
if @enquiry.save
format.html { redirect_to @enquiry, notice: 'Enquiry was successfully created.' }
format.json { render :show, status: :created, location: @enquiry }
else
format.html { render :new }
format.json { render json: @enquiry.errors, status: :unprocessable_entity }
end
end
end
#approved_enquiry_notification
# PATCH/PUT /enquiries/1
# PATCH/PUT /enquiries/1.json
def update
@enquiry = Enquiry.find(params[:id])
respond_to do |format|
if @enquiry.update(enquiry_params)
format.html { redirect_to @enquiry, notice: 'Enquiry was successfully updated.' }
format.json { render :show, status: :ok, location: @enquiry }
else
format.html { render :edit }
format.json { render json: @enquiry.errors, status: :unprocessable_entity }
end
end
end
# DELETE /enquiries/1
# DELETE /enquiries/1.json
def destroy
@enquiry.destroy
respond_to do |format|
format.html { redirect_to enquiries_url, notice: 'Enquiry was successfully destroyed.' }
format.json { head :no_content }
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_enquiry
@enquiry = Enquiry.find(params[:id])
end
# Never trust parameters from the scary internet, only allow the white list through.
#25-1 MG alle attributes hadden ook :id
def enquiry_params
params.require(:enquiry).permit(:id, :reference, :location, :description, :date, :amount, :approved, enquirymeasures_attributes: [:id, :responsible, :done, :needed, :measurement_id, :user],
tools_attributes: [:id, :handtool, :other, :motorvehicle, :compressor, :ramp, :scaffold, :crane, :ladder, :generator, :tankladder],
applicant_attributes: [:id, :name, :email, :contractor_id],
signatures_attributes: [:id, :date, :signature, :representative_id],
gasmeters_attributes: [:id, :date, :tester, :signature, :oxigen, :o_needed, :o_continu, :explosives, :e_needed, :e_continu, :mat1, :mat1_needed, :mat1_continu, :mat2, :mat2_needed, :mat2_continu, :mat3, :mat3_needed, :mat3_continu],
controls_attributes: [:id, :enquirycheck, :workspacecheck, :enquiry_id]).merge(user_id: current_user.id)
end
end
型号:
主要:
class Enquiry < ActiveRecord::Base
has_many :enquirymeasures, dependent: :destroy
accepts_nested_attributes_for :enquirymeasures, :reject_if => lambda { |a| a[:responsible].blank? }, :allow_destroy => true
has_many :tools, dependent: :destroy
accepts_nested_attributes_for :tools
has_many :controls, dependent: :destroy
accepts_nested_attributes_for :controls
has_one :applicant, dependent: :destroy
accepts_nested_attributes_for :applicant
has_one :contractor, through: :applicant
has_many :signatures, dependent: :destroy
accepts_nested_attributes_for :signatures
has_many :representatives , through: :signatures, :source => :representatives
has_many :gasmeters, dependent: :destroy
accepts_nested_attributes_for :gasmeters
belongs_to :user
#voor de goedkeuring mail
after_create :send_confirmation_mail
def send_confirmation_mail
ModelMailer.new_enquiry_mail(self).deliver
end
#after_update :send_approved_mail
#def send_approved_mail
# if params[:approved] == '1'
# if :approved == '1'
# ModelMailer.enquiry_approved_mailer(self).deliver
# end
#end
end
其中一个相关模型:
class Tool < ActiveRecord::Base
belongs_to :enquiry
end
我没有包括整个 _form,因为它很长(300 行)但给你一个想法:
<div class="form-group ">
<div class="panel-group" id="accordion" role="tablist" aria-multiselectable="true">
<%= f.fields_for :applicant do |a| %>
<div class="panel-group" id="accordion" role="tablist" aria-multiselectable="true">
<div class="panel panel-default">
<div class="panel-heading" role="tab" id="headingOne">
<h4 class="panel-title">
<a role="button" data-toggle="collapse" data-parent="#accordion" href="#collapseOne" aria-expanded="true" aria-controls="collapseOne">
Aanvraag
</a>
</h4>
</div>
<div id="collapseOne" class="panel-collapse collapse in" role="tabpanel" aria-labelledby="headingOne">
<div class="panel-body">
<%= f.label :Referentie, :class => "col-sm-2 control-label" %>
<%= f.text_field :reference, :class => "form-control" %> <br>
<%= f.label :Locatie, :class => "col-sm-2 control-label" %>
<%= f.select :location, [['Chemiepark', 'chemiepark'], ['Winschoten', 'winschoten'], ['Farmsum', 'farmsum']], :class => "form-control" %>
<br>
<br>
<%= f.label :Omschrijving, :class => "col-sm-2 control-label" %>
<%= f.text_area :description, :class => "form-control" %> <br>
<%= f.label :Aantal_uitvoerenden, :class => "col-sm-2 control-label" %>
<%= f.number_field :amount, :class => "form-control" %> <br>
<%= f.label :Datum %><br>
<%= f.datetime_select :date %> <br>
<%= a.label :Aanvrager %><br>
<%= a.text_field :name %> <br>
<%= a.label :email %><br>
<%= a.text_field :email %> <br>
<%= a.label :Aannemer %><br>
<%= a.collection_select(:contractor_id, Contractor.all, :id, :name, prompt: true) %>
</div>
</div>
</div>
</div>
<% end %>
你应该这样做:
def update
@enquiry = Enquiry.find(params[:id])
if @enquiry.update_attributes(enquiry_params)
# Handle a successful update.
else
render 'edit'
end
并从 enquiry_params 中删除 id。
您需要向每个嵌套属性添加 reject_if
子句,或者,如果您不希望表单默默地拒绝嵌套属性,则可以向每个单独的模型添加验证对于必填字段;这将针对您根据需要指定的任何内容回滚错误。
has_many :tools, dependent: :destroy
accepts_nested_attributes_for :tools, reject_if: :all_blank
has_many :controls, dependent: :destroy
accepts_nested_attributes_for :controls, reject_if: :all_blank
has_one :applicant, dependent: :destroy
accepts_nested_attributes_for :applicant, reject_if: :all_blank
has_one :contractor, through: :applicant
has_many :signatures, dependent: :destroy
accepts_nested_attributes_for :signatures, reject_if: :all_blank
has_many :representatives , through: :signatures, :source => :representatives
has_many :gasmeters, dependent: :destroy
accepts_nested_attributes_for :gasmeters, reject_if: :all_blank
附带说明一下,我发现 cocoon
gem 在处理嵌套表单时非常有用。
我进行了很多谷歌搜索,然后全部返回到将 :id 添加到允许的属性,但这在我的情况下不起作用,所以: 在编辑嵌套表单时如何防止创建多个空行(在相关表中)? 每次我编辑一个表格,它都会使空相关记录的数量增加一倍。
控制器:
class EnquiriesController < ApplicationController
before_action :authenticate_user!
load_and_authorize_resource
# before_action :set_enquiry, only: [:show, :edit, :update, :destroy]
#11-1-2017 Devise geinstalleerd, nog verder afmaken!(oa onderstaande uncommenten)
# GET /enquiries
# GET /enquiries.json
def index
# @enquiries = Enquiry.all
@enquirie = current_user.enquiries
end
# GET /enquiries/1
# GET /enquiries/1.json
def show
end
# GET /enquiries/new
def new
@enquiry = Enquiry.new
@enquiry.enquirymeasures.build
#@enquiry.measurements.build
@enquiry.tools.build
@enquiry.build_applicant
@enquiry.signatures.build
@enquiry.gasmeters.build
#@enquiry.enquirymeasures.build.build_measurement
end
# GET /enquiries/1/edit
def edit
#nog op kunnen slaan!!!! 1-01-17 Marco
@enquiry = Enquiry.find(params[:id])
@enquiry.enquirymeasures.build
@enquiry.tools.build
@enquiry.build_applicant
@enquiry.signatures.build
@enquiry.gasmeters.build
end
# POST /enquiries
# POST /enquiries.json
def create
@enquiry.user_id = current_user.id
@enquiry = Enquiry.new(enquiry_params)
#@enquiry.enquirymeasures.build
respond_to do |format|
if @enquiry.save
format.html { redirect_to @enquiry, notice: 'Enquiry was successfully created.' }
format.json { render :show, status: :created, location: @enquiry }
else
format.html { render :new }
format.json { render json: @enquiry.errors, status: :unprocessable_entity }
end
end
end
#approved_enquiry_notification
# PATCH/PUT /enquiries/1
# PATCH/PUT /enquiries/1.json
def update
@enquiry = Enquiry.find(params[:id])
respond_to do |format|
if @enquiry.update(enquiry_params)
format.html { redirect_to @enquiry, notice: 'Enquiry was successfully updated.' }
format.json { render :show, status: :ok, location: @enquiry }
else
format.html { render :edit }
format.json { render json: @enquiry.errors, status: :unprocessable_entity }
end
end
end
# DELETE /enquiries/1
# DELETE /enquiries/1.json
def destroy
@enquiry.destroy
respond_to do |format|
format.html { redirect_to enquiries_url, notice: 'Enquiry was successfully destroyed.' }
format.json { head :no_content }
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_enquiry
@enquiry = Enquiry.find(params[:id])
end
# Never trust parameters from the scary internet, only allow the white list through.
#25-1 MG alle attributes hadden ook :id
def enquiry_params
params.require(:enquiry).permit(:id, :reference, :location, :description, :date, :amount, :approved, enquirymeasures_attributes: [:id, :responsible, :done, :needed, :measurement_id, :user],
tools_attributes: [:id, :handtool, :other, :motorvehicle, :compressor, :ramp, :scaffold, :crane, :ladder, :generator, :tankladder],
applicant_attributes: [:id, :name, :email, :contractor_id],
signatures_attributes: [:id, :date, :signature, :representative_id],
gasmeters_attributes: [:id, :date, :tester, :signature, :oxigen, :o_needed, :o_continu, :explosives, :e_needed, :e_continu, :mat1, :mat1_needed, :mat1_continu, :mat2, :mat2_needed, :mat2_continu, :mat3, :mat3_needed, :mat3_continu],
controls_attributes: [:id, :enquirycheck, :workspacecheck, :enquiry_id]).merge(user_id: current_user.id)
end
end
型号: 主要:
class Enquiry < ActiveRecord::Base
has_many :enquirymeasures, dependent: :destroy
accepts_nested_attributes_for :enquirymeasures, :reject_if => lambda { |a| a[:responsible].blank? }, :allow_destroy => true
has_many :tools, dependent: :destroy
accepts_nested_attributes_for :tools
has_many :controls, dependent: :destroy
accepts_nested_attributes_for :controls
has_one :applicant, dependent: :destroy
accepts_nested_attributes_for :applicant
has_one :contractor, through: :applicant
has_many :signatures, dependent: :destroy
accepts_nested_attributes_for :signatures
has_many :representatives , through: :signatures, :source => :representatives
has_many :gasmeters, dependent: :destroy
accepts_nested_attributes_for :gasmeters
belongs_to :user
#voor de goedkeuring mail
after_create :send_confirmation_mail
def send_confirmation_mail
ModelMailer.new_enquiry_mail(self).deliver
end
#after_update :send_approved_mail
#def send_approved_mail
# if params[:approved] == '1'
# if :approved == '1'
# ModelMailer.enquiry_approved_mailer(self).deliver
# end
#end
end
其中一个相关模型:
class Tool < ActiveRecord::Base
belongs_to :enquiry
end
我没有包括整个 _form,因为它很长(300 行)但给你一个想法:
<div class="form-group ">
<div class="panel-group" id="accordion" role="tablist" aria-multiselectable="true">
<%= f.fields_for :applicant do |a| %>
<div class="panel-group" id="accordion" role="tablist" aria-multiselectable="true">
<div class="panel panel-default">
<div class="panel-heading" role="tab" id="headingOne">
<h4 class="panel-title">
<a role="button" data-toggle="collapse" data-parent="#accordion" href="#collapseOne" aria-expanded="true" aria-controls="collapseOne">
Aanvraag
</a>
</h4>
</div>
<div id="collapseOne" class="panel-collapse collapse in" role="tabpanel" aria-labelledby="headingOne">
<div class="panel-body">
<%= f.label :Referentie, :class => "col-sm-2 control-label" %>
<%= f.text_field :reference, :class => "form-control" %> <br>
<%= f.label :Locatie, :class => "col-sm-2 control-label" %>
<%= f.select :location, [['Chemiepark', 'chemiepark'], ['Winschoten', 'winschoten'], ['Farmsum', 'farmsum']], :class => "form-control" %>
<br>
<br>
<%= f.label :Omschrijving, :class => "col-sm-2 control-label" %>
<%= f.text_area :description, :class => "form-control" %> <br>
<%= f.label :Aantal_uitvoerenden, :class => "col-sm-2 control-label" %>
<%= f.number_field :amount, :class => "form-control" %> <br>
<%= f.label :Datum %><br>
<%= f.datetime_select :date %> <br>
<%= a.label :Aanvrager %><br>
<%= a.text_field :name %> <br>
<%= a.label :email %><br>
<%= a.text_field :email %> <br>
<%= a.label :Aannemer %><br>
<%= a.collection_select(:contractor_id, Contractor.all, :id, :name, prompt: true) %>
</div>
</div>
</div>
</div>
<% end %>
你应该这样做:
def update
@enquiry = Enquiry.find(params[:id])
if @enquiry.update_attributes(enquiry_params)
# Handle a successful update.
else
render 'edit'
end
并从 enquiry_params 中删除 id。
您需要向每个嵌套属性添加 reject_if
子句,或者,如果您不希望表单默默地拒绝嵌套属性,则可以向每个单独的模型添加验证对于必填字段;这将针对您根据需要指定的任何内容回滚错误。
has_many :tools, dependent: :destroy
accepts_nested_attributes_for :tools, reject_if: :all_blank
has_many :controls, dependent: :destroy
accepts_nested_attributes_for :controls, reject_if: :all_blank
has_one :applicant, dependent: :destroy
accepts_nested_attributes_for :applicant, reject_if: :all_blank
has_one :contractor, through: :applicant
has_many :signatures, dependent: :destroy
accepts_nested_attributes_for :signatures, reject_if: :all_blank
has_many :representatives , through: :signatures, :source => :representatives
has_many :gasmeters, dependent: :destroy
accepts_nested_attributes_for :gasmeters, reject_if: :all_blank
附带说明一下,我发现 cocoon
gem 在处理嵌套表单时非常有用。