我正在使用Rails构建一个简单的CRUD应用。到目前为止,我要为Players
设置CRUD。很快我将有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
。
players_controller.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
player.rb
class Player < ApplicationRecord
has_one :address
belongs_to :high_school_team, optional: true
belongs_to :club_team, optional: true
end
address.rb
class Address < ApplicationRecord
end
schema.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
用外键在模型上继续。
如果要在两个模型之间建立一对一关系,您将需要在其中添加一个“ belongs_to”,在另一个添加“ has_one”。怎么做你知道哪个吗?
区别在于放置外键的位置(它位于该表声明的belongs_to关联),但是您还应该考虑数据的实际含义。has_one关系表明某事是您的-那是,有些东西指向您。例如,它使更多说供应商拥有一个帐户比拥有一个帐户更有意义供应商。-Rails Guides: Associations