ruby-on-rails - Rails 4删除嵌套属性,只能在创建时使用,但不能在编辑/更新时使用

标签 ruby-on-rails ruby-on-rails-3 ruby-on-rails-4 nested-attributes

因此,我正在使用此Railscast

而且我知道Rails 4中针对Strong参数进行了一些更改。

First relevant question

Second relevant question

我已经四倍检查了我的实现,但看不到我要去哪里。就目前而言,在最初提交患者时(即创建方法)在“销毁”框中打勾会按预期工作,并将删除带有复选框的任何药物,并允许不带复选框的任何药物(从三种形式的输入中)它提供)。

但是,当我随后对该患者进行编辑时,所有未经检查要删除的药物都将被复制(因此我最终得到的附着药物比开始时要多),并且经过检查以删除的药物似乎没有变化。

因此,如果有两种药物附有“ Med1”和“ Med2”,并且由我编辑患者,如果两种药物都标记为删除,那么我仍然会以“ Med1”和“ Med2”结尾。如果仅将“ Med1”标记为删除,则我将得到“ Med1”和“ Med2”以及一个额外的“ Med2”。如果两个都没有标记为删除,我将分别以“ Med1”和“ Med2”两个结尾。

#patient.rb
class Patient < ActiveRecord::Base
has_many :procedures
has_many :medications, dependent: :destroy
has_many :previous_operations, dependent: :destroy

accepts_nested_attributes_for :medications, :allow_destroy => true, :reject_if => lambda { |a| a[:name].blank? },
end




#views/patients/_form.html.erb
<%= form_for(@patient) do |f| %>
  <% if @patient.errors.any? %>
    <div id="error_explanation">
      <h2><%= pluralize(@patient.errors.count, "error") %> prohibited this patient from being saved:</h2>

      <ul>
      <% @patient.errors.full_messages.each do |msg| %>
        <li><%= msg %></li>
      <% end %>
      </ul>
    </div>
  <% end %>

  <%= f.fields_for :medications do |builder| %>
    <%= render "medication_fields", :f => builder %>
  <% end %>

  <div class="field">
    <%= f.label :first_name %><br>
    <%= f.text_field :first_name %>
  </div>
  <div class="field">
    <%= f.label :last_name %><br>
    <%= f.text_field :last_name %>
  </div>
  <div class="actions">
    <%= f.submit %>
  </div>
<% end %>




#views/patients/medications_fields.html
<div class="field">
  <%= f.label :name %><br>
  <%= f.text_field :name %>
</div>
<div class="field">
  <%= f.label :_destroy, "Remove Medication" %>
  <%= f.check_box :_destroy %>
</div>




#controllers/patients_controller.rb
class PatientsController < ApplicationController
  before_action :set_patient, only: [:show, :edit, :update, :destroy]

  # GET /patients
  # GET /patients.json
  def index
    @patients = Patient.all
  end

  # GET /patients/1
  # GET /patients/1.json
  def show
  end

  # GET /patients/new
  def new
    @patient = Patient.new
    3.times { @patient.medications.build }
  end

  # GET /patients/1/edit
  def edit
  end

  # POST /patients
  # POST /patients.json
  def create
    @patient = Patient.new(patient_params)

    respond_to do |format|
      if @patient.save
        format.html { redirect_to @patient, notice: 'Patient was successfully created.' }
        format.json { render action: 'show', status: :created, location: @patient }
      else
        format.html { render action: 'new' }
        format.json { render json: @patient.errors, status: :unprocessable_entity }
      end
    end
  end

  # PATCH/PUT /patients/1
  # PATCH/PUT /patients/1.json
  def update
    respond_to do |format|
      if @patient.update(patient_params)
        format.html { redirect_to @patient, notice: 'Patient was successfully updated.' }
        format.json { head :no_content }
      else
        format.html { render action: 'edit' }
        format.json { render json: @patient.errors, status: :unprocessable_entity }
      end
    end
  end

  # DELETE /patients/1
  # DELETE /patients/1.json
  def destroy
    @patient.destroy
    respond_to do |format|
      format.html { redirect_to patients_url }
      format.json { head :no_content }
    end
    flash[:notice] = "Patient was successfully deleted."
  end

  private

    # Never trust parameters from the scary internet, only allow the white list through.
    def patient_params
      params.require(:patient).permit(:first_name, :last_name, medications_attributes: [:name, :_destroy])
    end

end


我一直非常小心,并通过强大的参数检查了:_destroy标志超过一百万次,但仍然没有骰子。

任何赞赏的帮助,一定是我看不到的显而易见的东西。

编辑

改变这个...

    # Never trust parameters from the scary internet, only allow the white list through.
    def patient_params
      params.require(:patient).permit(:first_name, :last_name, medications_attributes: [:name, :_destroy])
    end


为此...

    # Never trust parameters from the scary internet, only allow the white list through.
    def patient_params
      params.require(:patient).permit!
    end


似乎可以正常工作,因此我仍然确定这与强参数有关,但是我确定后者的安全性较差,不是最佳实践。

最佳答案

当你在做

# Never trust parameters from the scary internet, only allow the white list through.
def patient_params
  params.require(:patient).permit!
end


它允许您使用所有属性,因此不建议使用。这更像是黑客,而不是解决方案。

如果你看你的问题

Rails 4 deleting nested attributes, works on create but not on edit/update

如果你看你的参数允许

# Never trust parameters from the scary internet, only allow the white list through.
def patient_params
  params.require(:patient).permit(:first_name, :last_name, medications_attributes: [:name, :_destroy])
end


这将在创建患者时起作用,而不是在更新或编辑患者时起作用,因为当您创建新记录时,它不需要您允许id,但是当您要更新或编辑记录时,也需要允许其id。

固定:

只需将id属性传递给允许的属性,它将对您有用

# Never trust parameters from the scary internet, only allow the white list through.
def patient_params
  params.require(:patient).permit(:id, :first_name, :last_name, medications_attributes: [:id,:name, :_destroy])
end

关于ruby-on-rails - Rails 4删除嵌套属性,只能在创建时使用,但不能在编辑/更新时使用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24584816/

相关文章:

ruby-on-rails - 如何在 UTC 时区中创建 Rails 日志时间戳?

ruby-on-rails - 使用不同应用程序的单一登录接近 ruby​​ on rails

ruby-on-rails-4 - Rails 4 中的时差计算错误

ruby-on-rails - 跳过 :touch associations when saving an ActiveRecord object

ruby-on-rails - 在操作之前添加浅嵌套关联 Controller

ruby-on-rails - 带有 ActiveSupport 的 Rails 4 ActiveRecord 模块

ruby-on-rails - Ruby on Rails 回形针多重上传与嵌套属性

css - 在 Rails 应用程序 list 中使用 @import 时,您如何知道哪一行包含 SCSS 错误?

ruby-on-rails - Rails activerecord sort_by 不排序?在某些情况下

ruby-on-rails - 算法 ruby​​ (rails) 最佳分数数组