Rails数据库迁移报错求助:无法重定义主键'id'问题
解决Rails迁移中"you can't redefine the primary key column 'id'"错误
嘿,我一眼就看到问题出在哪了——你把迁移代码错误地塞进模型类里了,还有几个语法和数据库设计的小问题,咱们一步步来搞定它!
第一步:把模型和迁移代码分开
你的WaPlayer模型里根本不该有change方法(这是迁移文件的专属内容)。模型类只需要定义和业务相关的逻辑,比如关联、加密方法这些。
先修正你的app/models/wa_player.rb,改成这样:
class WaPlayer < ApplicationRecord has_secure_password end
第二步:修复迁移文件的语法和主键配置
打开你的迁移文件db/migrate/20180516070242_create_wa_players.rb,现在的问题有几个:
- 你尝试手动定义
id列,但Rails默认会自动生成整数类型的id主键,直接定义会冲突 - 如果你确实需要字符串类型的自定义主键,得先告诉Rails禁用默认主键,再手动定义
- 代码有语法错误(比如
t.id :String应该写成t.string :id),而且列名不符合Rails的蛇形命名规范
下面是修正后的迁移代码,我还调整了更合理的数据类型(比如金额用decimal、布尔状态用boolean,比全用string更靠谱):
class CreateWaPlayers < ActiveRecord::Migration[5.2] # 这里的版本要和你的Rails版本对应 def change # 先设置id: false,禁用默认的整数主键 create_table :wa_players, id: false do |t| t.string :id, primary_key: true # 定义字符串类型的主键id t.string :player_name # 把playerName改成蛇形命名的player_name t.string :uuid t.string :password_digest # 划重点!has_secure_password需要的是password_digest,不是password t.decimal :money # 金额用decimal比string更适合计算 t.integer :items_sold # 交易数量用integer更合理 t.integer :items_bought t.decimal :earnt t.decimal :spent t.string :permissions # 把Permissions改成小写蛇形 t.boolean :locked # 锁定状态用boolean类型,比string更直观 t.timestamps null: false end add_index :wa_players, :id, unique: true # 主键会自动加索引,这里写出来更明确 end end
第三步:重新运行迁移
如果之前已经尝试过错误的迁移,先回滚:
rails db:rollback
然后再执行正确的迁移:
rails db:migrate
额外选项:如果你不需要自定义主键
要是你其实只是不小心多写了id列,根本不需要字符串主键,那更简单——直接去掉id: false和t.string :id,Rails会自动帮你生成整数类型的主键id,迁移文件会更简洁:
class CreateWaPlayers < ActiveRecord::Migration[5.2] def change create_table :wa_players do |t| t.string :player_name t.string :uuid t.string :password_digest t.decimal :money t.integer :items_sold t.integer :items_bought t.decimal :earnt t.decimal :spent t.string :permissions t.boolean :locked t.timestamps null: false end end end
内容的提问来源于stack exchange,提问作者Lars Erhardt
相关产品推荐
相关产品推荐

