ruby on rails - Rails 4 borra atributos anidados, funciona en crear pero no en editar/actualizar
ruby-on-rails ruby-on-rails-3 (1)
cuando estas haciendo
# Never trust parameters from the scary internet, only allow the white list through.
def patient_params
params.require(:patient).permit!
end
Permite todos tus atributos y no es recomendable . Es más un hack que una solución.
Si miras tu pregunta
Rails 4 deleting nested attributes, works on create but not on edit/update
y si miras a tus params permitidos
# 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
Esto funcionará para crear pacientes, pero no para actualizarlos o editarlos, porque cuando creas un nuevo registro, no es necesario que permitas la identificación, pero cuando quieres actualizar o editar un registro también necesitas que se permita su identificación .
Fijar:
Simplemente pase el atributo id a los atributos permitidos y funcionará para usted
# 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
Así que estoy trabajando desde este Railscast .
Y soy consciente de que ha habido algunos cambios en Rails 4 para los parámetros Strong.
He revisado cuádruple mi implementación, pero no puedo ver dónde me equivoco. Tal como está en este momento, marcar la casilla "destruir" cuando se envía al paciente inicialmente (es decir, el método de creación) funciona según lo previsto, y eliminará cualquier medicamento que tenga una casilla marcada y permitirá que no lo haga (de las tres entradas del formulario proporciona).
Sin embargo, cuando posteriormente edito a ese paciente, todos los medicamentos que no se verifican para ser eliminados se duplican (por lo que termino con más medicamentos adjuntos de los que comencé), y los que se verifican para su eliminación no parecen cambiar.
Entonces, si hay dos medicamentos adjuntos "Med1" y "Med2", y edito al paciente, si ambos están marcados para su eliminación, terminaré con "Med1" y "Med2". Si solo se marca "Med1" para su eliminación, terminaré con "Med1" y "Med2" y un "Med2" adicional. Si ninguno de los dos está marcado para su eliminación, terminaré con dos de cada "Med1" y "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
He sido súper cuidadoso y he comprobado más de un millón de veces que se permite: _destroy flag a través de parámetros fuertes, pero aún no hay dados.
Cualquier ayuda apreciada, debe ser algo obvio que simplemente no puedo ver.
EDITAR
Cambiando esto ...
# 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
A esto...
# Never trust parameters from the scary internet, only allow the white list through.
def patient_params
params.require(:patient).permit!
end
Parece funcionar correctamente, así que todavía estoy seguro de que es algo que tiene que ver con parámetros sólidos, pero estoy seguro de que este último es menos seguro y no es la mejor práctica.