ruby-on-rails - 尝试更新时基本 CRUD 应用程序出错:ActiveRecord::StatementInvalid (SQLite3::SQLException: no such column:addresses.player_id)
问题描述
我正在用 Rails 构建一个简单的 CRUD 应用程序。到目前为止,我已经完成了 CRUD 的Players
. 很快我就会有HighSchoolTeams
,ClubTeams
和Addresses
.
当我尝试更新现有播放器时遇到问题。我收到以下错误:
Started PATCH "/players/3" for ::1 at 2019-12-13 13:43:53 -0800
Processing by PlayersController#update as JS
Parameters: {"authenticity_token"=>"2fyMlnOWCTn5pt8pyf/W86fRjCO4Af85sbl+3RFDg2OIXAU+T2wU7VxEU3gAxOZPNXvYDcjYpNXMWhImJiEkDQ==", "player"=>{"first_name"=>"Ben", "middle_name"=>"Patrick", "last_name"=>"Stein", "height"=>"", "weight"=>"", "birthday"=>"", "high_school_team"=>"", "club_team"=>"", "email"=>"", "phone_number"=>"", "address_line_one"=>"", "address_line_two"=>"", "city"=>"", "state"=>"", "zip"=>"", "notes"=>""}, "commit"=>"Update Player", "id"=>"3"}
Player Load (0.2ms) SELECT "players".* FROM "players" WHERE "players"."id" = ? LIMIT ? [["id", 3], ["LIMIT", 1]]
↳ app/controllers/players_controller.rb:30:in `update'
(0.1ms) begin transaction
↳ app/controllers/players_controller.rb:32:in `update'
Address Load (0.7ms) SELECT "addresses".* FROM "addresses" WHERE "addresses"."player_id" = ? LIMIT ? [["player_id", 3], ["LIMIT", 1]]
↳ app/controllers/players_controller.rb:32:in `update'
(0.1ms) rollback transaction
↳ app/controllers/players_controller.rb:32:in `update'
Completed 500 Internal Server Error in 14ms (ActiveRecord: 1.4ms | Allocations: 5907)
ActiveRecord::StatementInvalid (SQLite3::SQLException: no such column: addresses.player_id):
app/controllers/players_controller.rb:32:in `update'
我不确定错误发生了什么。确实没有addresses.player_id
专栏。我不打算在那里。我的目的是让玩家Address
通过address_id
专栏来参考。
在查看我的代码时,我没有发现任何问题。有效负载已成功到达服务器,并且正在成功加载播放器。问题出在@player.update
.
玩家控制器.rb
class PlayersController < ApplicationController
...
def edit
@player = Player.find(params[:id])
end
def update
@player = Player.find(params[:id])
if @player.update(player_params)
redirect_to @player
else
render 'edit'
end
end
private
def player_params
params_for_player = params
.require(:player)
.permit(:first_name, :middle_name, :last_name, :height, :weight, :birthday, :high_school_team, :club_team, :email, :phone_number, :address_line_one, :address_line_two, :city, :state, :zip, :notes)
.except(:address_line_one, :address_line_two, :city, :state, :zip)
params_for_player["address"] = nil
params_for_player["high_school_team"] = nil
params_for_player["club_team"] = nil
return params_for_player
end
end
播放器.rb
class Player < ApplicationRecord
has_one :address
belongs_to :high_school_team, optional: true
belongs_to :club_team, optional: true
end
地址.rb
class Address < ApplicationRecord
end
架构.rb
ActiveRecord::Schema.define(version: 2019_12_12_025909) do
create_table "addresses", force: :cascade do |t|
t.string "line_one"
t.string "line_two"
t.string "city"
t.string "state"
t.string "zip"
t.datetime "created_at", precision: 6, null: false
t.datetime "updated_at", precision: 6, null: false
end
create_table "club_teams", force: :cascade do |t|
t.string "name"
t.datetime "created_at", precision: 6, null: false
t.datetime "updated_at", precision: 6, null: false
end
create_table "high_school_teams", force: :cascade do |t|
t.string "name"
t.datetime "created_at", precision: 6, null: false
t.datetime "updated_at", precision: 6, null: false
end
create_table "players", force: :cascade do |t|
t.string "first_name"
t.string "middle_name"
t.string "last_name"
t.decimal "height"
t.decimal "weight"
t.date "birthday"
t.integer "high_school_team_id"
t.integer "club_team_id"
t.string "email"
t.string "phone_number"
t.integer "address_id"
t.text "notes"
t.datetime "created_at", precision: 6, null: false
t.datetime "updated_at", precision: 6, null: false
t.index ["address_id"], name: "index_players_on_address_id"
t.index ["club_team_id"], name: "index_players_on_club_team_id"
t.index ["high_school_team_id"], name: "index_players_on_high_school_team_id"
end
add_foreign_key "players", "addresses"
add_foreign_key "players", "club_teams"
add_foreign_key "players", "high_school_teams"
end
解决方案
我打算让玩家通过拥有 address_id 列来引用地址。
class Player
belongs_to :address
end
class Address
has_one :player
end
belongs_to
使用外键继续模型。但我会说这不是很合乎逻辑。addresses
应该有一个player_id
和belong_to :player
。它是玩家的地址,反之亦然。
如果您想在两个模型之间建立一对一的关系,您需要将belongs_to 添加到一个模型,并将has_one 添加到另一个模型。你怎么知道哪个是哪个?
区别在于您放置外键的位置(它位于表中,用于声明belongs_to 关联的类),但您也应该考虑数据的实际含义。has_one 关系表示某物是你的——也就是说,某物指向你。例如,说供应商拥有客户比说客户拥有供应商更有意义。
- Rails 指南:关联
推荐阅读
- intellij-idea - IDEA编辑器中字符的宽度不一样
- http - netcat - 接收包含多个文件的多部分 TCP/HTTP 响应
- javascript - Window.top.opener is null/undefined in the child window opened from gmail in all browsers
- mysql - 在 Istio 中连接到 MySQL (AWS RDS)
- android - tensorflow-lite and nnapi hw acceleration for embedded linux
- php - Can't view records based on selected drop down values from two drop downs
- android - 无法完成刷新条目的计划请求。ClientErrorCode: 3 Android Kotlin
- python - django 查询集 select_related 。values() 重命名键
- java - 使用 Java 在 flink 中对 JSON 进行聚合
- reactjs - 在 react-native 中动态更改 View 的背景颜色