web-dev-qa-db-ja.com

Rails 4ネストされた属性の削除、作成では機能しますが、編集/更新では機能しません

だから私はこれから働いています Railscast

そして、StrongパラメーターのRails 4にいくつかの変更があったことを認識しています。

最初の関連する質問

2番目の関連する質問

実装を4回チェックしましたが、どこが間違っているのかわかりません。現時点では、患者を最初に送信するときに「破棄」ボックスにチェックマークを付けると(つまり、createメソッド)、意図したとおりに機能し、チェックボックスがオンになっている薬剤を削除し、チェックボックスがオンになっていない薬剤を許可します(3つのフォーム入力から)それが提供します)。

ただし、その後その患者を編集すると、チェックされて削除されない薬が重複します(そのため、私よりも多くの薬が添付されてしまいますで始まり、削除がチェックされたものは変更されていないようです。

したがって、「Med1」と「Med2」の2つの薬が添付されていて、患者を編集した場合、両方に削除のマークが付けられていても、「Med1」と「Med2」になります。 「Med1」のみが削除対象としてマークされている場合、「Med1」と「Med2」、および追加の「Med2」が表示されます。どちらも削除のマークが付いていない場合、「Med1」と「Med2」がそれぞれ2つずつ表示されます。

#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フラグを100万回以上チェックしましたが、それでもサイコロはありません。

どんな助けでも感謝します、私がただ見ることができない明白な何かでなければなりません。

[〜#〜]編集[〜#〜]

これを変更...

    # 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

正しく動作しているように見えるので、それは強力なパラメータと関係があると確信していますが、後者は安全性が低いと確信しており、ベストプラクティスではありません。

16
Jeremy E

あなたがしているとき

# 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
34
Mandeep