请求参数过滤HABTM模型关系的更新操作

时间:2014-01-21 02:11:38

标签: ruby-on-rails ruby activerecord entity-relationship

医生可以在许多医院进行手术。

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

在更新方法中,@doctor已设置:set_doctor已从难以捉摸的“params”中获取了医生的ID并找到了记录,这一切都很好。

但是看看医生的参数!! - &GT; 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"
}

那是怎么回事?我假设paramsrequest.params获取数据,那为什么它会丢失hospital_ids

@doctor.update(doctor_params)显然没有更新任何医院的模型。

有什么想法吗?

1 个答案:

答案 0 :(得分:1)

对于HABTM,请使用如下所示的参数:

  def doctor_params
    params.require(:doctor).permit(:first_name, :last_name, :email, :status, :notes, {:hospital_ids => []})
  end

参考 - https://coderwall.com/p/_1oejq