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
因为型号名称是 BloodGroup
而 BloodGroup
的 snake_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
我的 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
因为型号名称是 BloodGroup
而 BloodGroup
的 snake_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