Доктор может выполнять операции во многих больницах.Запрос фильтрации параметров при действии обновления отношения модели HABTM
class Doctor < ActiveRecord::Base
has_and_belongs_to_many :hospitals
end
В больнице может быть много врачей, выполняющих в ней операции.
class Hospital < ActiveRecord::Base
has_and_belongs_to_many :doctors
end
Новая миграция таблицы соединений выглядит следующим образом.
class CreateDoctorsHospitals < ActiveRecord::Migration
def change
create_table :doctors_hospitals, id: false do |t|
t.belongs_to :doctor
t.belongs_to :hospital
t.timestamps
end
end
end
Мы хотели бы обновить @doctor
объект и дать ему некоторые больницы.
<%= form_for(@doctor) do |f| %>
<%= f.label :notes %><br>
<%= f.text_area :notes %><br>
<%= f.label :hospitals %><br>
<%= f.collection_select :hospital_ids, Hospital.all, :id, :name, {}, { multiple: true } %><br>
<%= f.submit %>
<% end %>
Сгенерированный HTML-код выглядит следующим образом.
<form accept-charset="UTF-8" action="/doctors/1" class="edit_doctor" id="edit_doctor_1" method="post">
<div>
<input name="utf8" type="hidden" value="✓">
<input name="_method" type="hidden" value="patch">
<input name="authenticity_token" type="hidden" value="xxx">
</div>
<label for="doctor_notes">Notes</label><br>
<textarea id="doctor_notes" name="doctor[notes]"></textarea><br>
<label class="control-label" for="doctor_hospitals">Hospitals</label><br>
<input name="doctor[hospital_ids][]" type="hidden" value="">
<select class="form-control" id="doctor_hospital_ids" multiple="multiple" name="doctor[hospital_ids][]">
<option value="1">First Hospital</option>
<option value="2">Second Hospital</option>
...
<option value="n">Nth Hospital</option
</select>
<input name="commit" type="submit" value="Update Doctor">
</form>
Соответствующие фрагменты DoctorsController находятся здесь.
class DoctorsController < ApplicationController
before_action :set_doctor, only: [:show, :edit, :update, :destroy]
def update
respond_to do |format|
if @doctor.update(doctor_params)
format.html { redirect_to edit_doctor_hospitals_path, notice: 'Doctor was successfully updated.' }
format.json { head :no_content }
else
format.html { render action: 'edit' }
format.json { render json: @doctor.errors, status: :unprocessable_entity }
end
end
end
def set_doctor
@doctor = Doctor.find(params[:id])
end
def doctor_params
params.require(:doctor).permit(:first_name, :last_name, :email, :status, :notes, :hospital_ids)
end
end
Хотя в методе Update, @doctor
было установлено: set_doctor
захватил идентификатор врача из неуловимых «params
» и нашел запись, и все это хорошо.
Но посмотрите на врача param! ->params[:doctor]=>{"notes"=>"Here be notes"}
. Где hospital_ids
? Вот что params
выглядит следующим образом:
{
"utf8"=>"✓",
"_method"=>"patch",
"authenticity_token"=>"xxx",
"doctor"=>{
"notes"=>"Here be notes"
},
"commit"=>"Update Doctor",
"action"=>"update",
"controller"=>"doctors",
"id"=>"1"
}
Если посмотреть в request.params
в этот же самый момент, мы увидим, что она включает в себя hospital_ids
! Замечательно!
{
"utf8"=>"✓",
"_method"=>"patch",
"authenticity_token"=>"xxx",
"doctor"=>{
"notes"=>"Here be notes",
"hospital_ids"=>["", "1", "4", "10"] # I don't know what that blank one is for, but whatever.
},
"commit"=>"Update Doctor",
"action"=>"update",
"controller"=>"doctors",
"id"=>"1"
}
Так что же происходит? Я предполагаю, что params
получает свои данные от request.params
, так почему он теряет hospital_ids
?
@doctor.update(doctor_params)
, очевидно, не обновляет модель с больницами.
Любые идеи?
Ого! Это полностью. Благодарю вас за это. – trainface