Rails collection_select 不适用于多对一关系

Rails collection_select not working for many to one relationship

我的 rails 项目中有 3 个模型

患者

class Patient < ActiveRecord::Base
    has_many :temperatures
    belongs_to :bloodgroup
    def fullname
        "#{firstName} #{surname}"
    end
end

温度

class Temperature < ActiveRecord::Base
    belongs_to :patient
end

血型

class BloodGroup < ActiveRecord::Base
    has_many :patients
end

collection_select 使用以下代码段

将患者添加到温度中
<div class="field">
    <%= f.label :patient_id %><br>
    <%= collection_select(:temperature, :patient_id, Patient.all, :id, :fullname, prompt: true) %>
</div>

但是下面的代码片段 - 将 BloodGroup 添加到患者身上不起作用

<div class="field">
    <%= f.label :bloodgroup_id %><br>
    <%= collection_select(:Patient, :bloodgroup_id, BloodGroup.all, :id, :id, prompt: true) %>
</div>

我不确定我是否没有正确设置 collection_select 或者我是否没有正确设置关联,因为我是 rails 的新手所以任何帮助都会不胜感激。

更新

create_table "blood_groups", force: :cascade do |t|
    t.string   "bloodgroup"
    t.datetime "created_at", null: false
    t.datetime "updated_at", null: false
end
create_table "patients", force: :cascade do |t|
    t.string   "firstName"
    t.string   "surname"
    t.datetime "created_at",    null: false
    t.datetime "updated_at",    null: false
    t.integer  "bloodgroup_id"
end
create_table "temperatures", force: :cascade do |t|
    t.integer  "patient_id"
    t.decimal  "temperature"
    t.datetime "dt"
    t.datetime "created_at",  null: false
    t.datetime "updated_at",  null: false
end

控制器

患者

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
  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 :show, status: :created, location: @patient }
      else
        format.html { render :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 { render :show, status: :ok, location: @patient }
      else
        format.html { render :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, notice: 'Patient was successfully destroyed.' }
      format.json { head :no_content }
    end
  end

  private
    # Use callbacks to share common setup or constraints between actions.
    def set_patient
      @patient = Patient.find(params[:id])
    end

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

温度

class TemperaturesController < ApplicationController
  before_action :set_temperature, only: [:show, :edit, :update, :destroy]

  # GET /temperatures
  # GET /temperatures.json
  def index
    @temperatures = Temperature.all
  end

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

  # GET /temperatures/new
  def new
    @temperature = Temperature.new
  end

  # GET /temperatures/1/edit
  def edit
  end

  # POST /temperatures
  # POST /temperatures.json
  def create
    @temperature = Temperature.new(temperature_params)

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

  # PATCH/PUT /temperatures/1
  # PATCH/PUT /temperatures/1.json
  def update
    respond_to do |format|
      if @temperature.update(temperature_params)
        format.html { redirect_to @temperature, notice: 'Temperature was successfully updated.' }
        format.json { render :show, status: :ok, location: @temperature }
      else
        format.html { render :edit }
        format.json { render json: @temperature.errors, status: :unprocessable_entity }
      end
    end
  end

  # DELETE /temperatures/1
  # DELETE /temperatures/1.json
  def destroy
    @temperature.destroy
    respond_to do |format|
      format.html { redirect_to temperatures_url, notice: 'Temperature was successfully destroyed.' }
      format.json { head :no_content }
    end
  end

  private
    # Use callbacks to share common setup or constraints between actions.
    def set_temperature
      @temperature = Temperature.find(params[:id])
    end

    # Never trust parameters from the scary internet, only allow the white list through.
    def temperature_params
      params.require(:temperature).permit(:patient_id, :temperature, :dt)
    end
end

血型

class BloodGroupsController < ApplicationController
  before_action :set_blood_group, only: [:show, :edit, :update, :destroy]

  # GET /blood_groups
  # GET /blood_groups.json
  def index
    @blood_groups = BloodGroup.all
  end

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

  # GET /blood_groups/new
  def new
    @blood_group = BloodGroup.new
  end

  # GET /blood_groups/1/edit
  def edit
  end

  # POST /blood_groups
  # POST /blood_groups.json
  def create
    @blood_group = BloodGroup.new(blood_group_params)

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

  # PATCH/PUT /blood_groups/1
  # PATCH/PUT /blood_groups/1.json
  def update
    respond_to do |format|
      if @blood_group.update(blood_group_params)
        format.html { redirect_to @blood_group, notice: 'Blood group was successfully updated.' }
        format.json { render :show, status: :ok, location: @blood_group }
      else
        format.html { render :edit }
        format.json { render json: @blood_group.errors, status: :unprocessable_entity }
      end
    end
  end

  # DELETE /blood_groups/1
  # DELETE /blood_groups/1.json
  def destroy
    @blood_group.destroy
    respond_to do |format|
      format.html { redirect_to blood_groups_url, notice: 'Blood group was successfully destroyed.' }
      format.json { head :no_content }
    end
  end

  private
    # Use callbacks to share common setup or constraints between actions.
    def set_blood_group
      @blood_group = BloodGroup.find(params[:id])
    end

    # Never trust parameters from the scary internet, only allow the white list through.
    def blood_group_params
      params.require(:blood_group).permit(:bloodgroup)
    end
end

日志

Started POST "/patients" for 81.144.132.166 at 2017-08-25 12:10:08 +0000
Cannot render console from 81.144.132.166! Allowed networks: 127.0.0.1, ::1, 127.0.0.0/127.255.255.255
Processing by PatientsController#create as HTML
  Parameters: {"utf8"=>"✓", "authenticity_token"=>"KnDRbEAL/f1DK6Gc9TcFNu0rRH5tahnGZiwLcx6FqH5iP7L5BsMOjH0yKR3630g/4ejCLUzilloj1rkO86wkAA==", "patient"=>{"firstName"=>"Test", "surname"=>"test", "bloodgroup_id"=>"7"}, "commit"=>"Create Patient"}
Unpermitted parameter: bloodgroup_id
   (0.1ms)  begin transaction
  SQL (41.7ms)  INSERT INTO "patients" ("firstName", "surname", "created_at", "updated_at") VALUES (?, ?, ?, ?)  [["firstName", "Test"], ["surname", "test"], ["created_at", "2017-08-25 12:10:08.979026"], ["updated_at", "2017-08-25 12:10:08.979026"]]
   (10.1ms)  commit transaction
Redirected to https://healthy-rails-conorsmalley.c9users.io/patients/6
Completed 302 Found in 125ms (ActiveRecord: 51.8ms)


Started GET "/patients/6" for 81.144.132.166 at 2017-08-25 12:10:09 +0000
Cannot render console from 81.144.132.166! Allowed networks: 127.0.0.1, ::1, 127.0.0.0/127.255.255.255
Processing by PatientsController#show as HTML
  Parameters: {"id"=>"6"}
  Patient Load (0.4ms)  SELECT  "patients".* FROM "patients" WHERE "patients"."id" = ? LIMIT 1  [["id", 6]]
  Rendered patients/show.html.erb within layouts/application (0.4ms)
Completed 200 OK in 32ms (Views: 29.2ms | ActiveRecord: 0.4ms)

当我按下提交为患者添加血型时,我得到以下日志

Started POST "/patients" for 81.144.132.166 at 2017-08-25 12:40:03 +0000
Cannot render console from 81.144.132.166! Allowed networks: 127.0.0.1, ::1, 127.0.0.0/127.255.255.255
Processing by PatientsController#create as HTML
  Parameters: {"utf8"=>"✓", "authenticity_token"=>"Mkw0f3Yu6jXqzc+wBgbLxDDbW8GJY41ARBme0St/JIV6A1fqMOYZRNTURzEJ7obNPBjdkqjrAtwB4yysxlao+w==", "patient"=>{"firstName"=>"asdf", "surname"=>"ghjk"}, "Patient"=>{"bloodgroup_id"=>"3"}, "commit"=>"Create Patient"}
   (0.1ms)  begin transaction
  SQL (0.4ms)  INSERT INTO "patients" ("firstName", "surname", "created_at", "updated_at") VALUES (?, ?, ?, ?)  [["firstName", "asdf"], ["surname", "ghjk"], ["created_at", "2017-08-25 12:40:03.623102"], ["updated_at", "2017-08-25 12:40:03.623102"]]
   (9.6ms)  commit transaction
Redirected to https://healthy-rails-conorsmalley.c9users.io/patients/8
Completed 302 Found in 15ms (ActiveRecord: 10.2ms)


Started GET "/patients/8" for 81.144.132.166 at 2017-08-25 12:40:03 +0000
Cannot render console from 81.144.132.166! Allowed networks: 127.0.0.1, ::1, 127.0.0.0/127.255.255.255
Processing by PatientsController#show as HTML
  Parameters: {"id"=>"8"}
  Patient Load (0.2ms)  SELECT  "patients".* FROM "patients" WHERE "patients"."id" = ? LIMIT 1  [["id", 8]]
  Rendered patients/show.html.erb within layouts/application (0.5ms)
Completed 200 OK in 23ms (Views: 21.4ms | ActiveRecord: 0.2ms)

您的代码中有一些错误可能会导致问题

1)

belongs_to :bloodgroup

应该是

belongs_to :blood_group

因为型号名称是 BloodGroupBloodGroupsnake_case 字符串是 blood_group 而不是 bloodgroup

2)

<%= collection_select(:Patient, :bloodgroup_id, BloodGroup.all, :id, :id, prompt: true) %>

应该是

<%= collection_select(:patient, :blood_group_id, BloodGroup.all, :id, :id, prompt: true) %>

更新:

My db schema has the column bloodgroup_id not blood_group_id

然后您需要指定您与 自定义外键 的关联,否则默认情况下 Rails 将查找 blood_group_id

class Patient < ActiveRecord::Base
  has_many :temperatures
  belongs_to :blood_group, foreign_key: "bloodgroup_id"

  def fullname
    "#{firstName} #{surname}"
  end
end

Unpermitted parameter: bloodgroup_id

您需要在 patient_params 中允许 bloodgroup_id 才能将其保存到 DB

def patient_params
  params.require(:patient).permit(:firstName, :surname, bloodgroup_id)
end