Heroku Rails 数据库迁移文件顺序和关系
Heroku Rails db migration file order and relationships
我有一个 User
模型和一个 Role
模型。当我开始构建应用程序时,我首先创建 User
模型,生成的迁移文件包含对角色的引用:
class CreateUsers < ActiveRecord::Migration[5.0]
def change
create_table :users do |t|
t.string :first_name
t.string :last_name
t.string :username
t.string :email
t.string :password
t.string :password_digest
t.boolean :banned
t.references :role, foreign_key: true
t.timestamps
end
end
end
然后我创建了生成此迁移文件的 Role
模型:
class CreateRoles < ActiveRecord::Migration[5.0]
def change
create_table :roles do |t|
t.string :title
t.integer :access_level
t.timestamps
end
end
end
我正在尝试使用以下命令 heroku run rails db:migrate
(使用 Rails 5)根据文档部署到 Heroku 并迁移我的数据库。
我从 Heroku 收到一条错误消息:
heroku run rake db:migrate
Running rake db:migrate on ⬢ gentle-headland-79177... up, run.9293 (Free)
D, [2016-12-31T08:15:33.131367 #4] DEBUG -- : (90.7ms) CREATE TABLE "schema_migrations" ("version" character varying PRIMARY KEY)
D, [2016-12-31T08:15:33.152682 #4] DEBUG -- : (11.5ms) CREATE TABLE "ar_internal_metadata" ("key" character varying PRIMARY KEY, "value" character varying, "created_at" timestamp NOT NULL, "updated_at" timestamp NOT NULL)
D, [2016-12-31T08:15:33.155373 #4] DEBUG -- : (1.1ms) SELECT pg_try_advisory_lock(6845940114126317925);
D, [2016-12-31T08:15:33.172106 #4] DEBUG -- : ActiveRecord::SchemaMigration Load (1.2ms) SELECT "schema_migrations".* FROM "schema_migrations"
I, [2016-12-31T08:15:33.178453 #4] INFO -- : Migrating to CreateUsers (20161117083901)
D, [2016-12-31T08:15:33.181903 #4] DEBUG -- : (0.9ms) BEGIN
== 20161117083901 CreateUsers: migrating ======================================
-- create_table(:users)
D, [2016-12-31T08:15:33.199351 #4] DEBUG -- : (13.4ms) CREATE TABLE "users" ("id" serial primary key, "first_name" character varying, "last_name" character varying, "username" character varying, "email" character varying, "password" character varying, "password_digest" character varying, "banned" boolean, "role_id" integer, "created_at" timestamp NOT NULL, "updated_at" timestamp NOT NULL, CONSTRAINT "fk_rails_642f17018b"
FOREIGN KEY ("role_id")
REFERENCES "roles" ("id")
)
D, [2016-12-31T08:15:33.200707 #4] DEBUG -- : (1.0ms) ROLLBACK
D, [2016-12-31T08:15:33.202190 #4] DEBUG -- : (1.2ms) SELECT pg_advisory_unlock(6845940114126317925)
rake aborted!
StandardError: An error has occurred, this and all later migrations canceled:
PG::UndefinedTable: ERROR: relation "roles" does not exist
: CREATE TABLE "users" ("id" serial primary key, "first_name" character varying, "last_name" character varying, "username" character varying, "email" character varying, "password" character varying, "password_digest" character varying, "banned" boolean, "role_id" integer, "created_at" timestamp NOT NULL, "updated_at" timestamp NOT NULL, CONSTRAINT "fk_rails_642f17018b"
FOREIGN KEY ("role_id")
REFERENCES "roles" ("id")
)
据我了解,Heroku 似乎希望先定义 Role
,然后再定义 User
。
为什么在我的本地机器上,我可以 db:migrate 正常,但在 Heroku 上却失败了?
Sqlite3 和 Postgresql 之间的区别?
我该如何解决这个部署问题?
我是否只是将我的 create_role 迁移文件重命名为具有比 create_user 迁移文件更早的时间戳?这甚至是推荐的做法吗? :D
更新
我将我的存储库 git 克隆到我的 iMac 上的桌面文件夹。
然后我 运行 rails db:migrate
在那个新的本地副本上。
没有任何错误。所有数据库迁移 运行、所有 table 以及所有关系都已到位。 Heroku 端确实有些问题。
更新 2
再次将我的存储库签出到一个新的桌面文件夹中,运行 bundle install
然后尝试了这个版本的 db:migrate 命令:
rails db:migrate RAILS_ENV=production
我看到关于角色不存在的相同错误输出
然而
然后我创建了一个 b运行d 全新的 rails 项目 honey
:
rails new honey
做过bundle install
然后去了:
rails generate model User name:string role:references
最后,我去了:
rails db:migrate RAILS_ENV=production
没有错误...
我显然没有生成任何 Role
模型,为什么它没有失败?
这是控制台日志:
Warlocks-iMac:bad clementwu$ cd honey/
Warlocks-iMac:honey clementwu$ ls
Gemfile Rakefile config lib test
Gemfile.lock app config.ru log tmp
README.md bin db public vendor
Warlocks-iMac:honey clementwu$ rails generate model User name:string role:references
Running via Spring preloader in process 27200
Expected string default value for '--jbuilder'; got true (boolean)
invoke active_record
create db/migrate/20170101100613_create_users.rb
create app/models/user.rb
invoke test_unit
create test/models/user_test.rb
create test/fixtures/users.yml
Warlocks-iMac:honey clementwu$ rails db:migrate RAILS_ENV=production
== 20170101100613 CreateUsers: migrating ======================================
-- create_table(:users)
-> 0.0018s
== 20170101100613 CreateUsers: migrated (0.0018s) =============================
Warlocks-iMac:honey clementwu$
数据库已创建,甚至显示 role_id
外键,尽管我的生产数据库中没有 table 调用 role
:
莫名其妙:D
更新 3
也许这是sqlite3数据库和postgresql数据库的区别。
默认情况下,rails 应用程序 config/database.yml
指定生产数据库称为 db/production.sqlite3
,即它不使用 PostgreSQL 数据库,因此它不提供关于角色不存在的错误。
根据这个 Whosebug post:Does SQLite support referential integrity?
看来 SQLite3 没有保证运行引用完整性:(
屁股很痛。
幸好这只是个人学习项目,不是工作项目。
从 PostgreSQL 开始也不太可行,您不能像使用 SQLite3 和 Rails CLI 那样轻松地删除和重新创建数据库。
我想这里要吸取的教训是认真思考并首先创建依赖项 table。
Do I just rename my create_role migration file to have an earlier timestamp than the create_user migration file? Is that even recommended practice ? :D
是的,你的情况没问题。
但是 请记住,当您从一开始就搭建系统时,这样做是可以的。拥有生产数据库后,您应该确保迁移 运行 在部署之前成功。
所以这只是对未来的提示,这里是我自己的生产部署最佳实践
转储您的生产数据库。你可以用
pg_dump <db_name> > <dump_file>; scp <server>:<path_to_dump_file> ./
或https://github.com/sgruhier/capistrano-db-tasks
如果是 heroku,这里很好 article
在本地环境中应用
psql <db_name> < <dump_file>
尝试运行迁移
如果一切出错,请转到第 5 步,否则转到第 6 步
修复迁移问题转到步骤 4
检查迁移是否不会损坏数据,如果它尝试修复迁移并从第 2 步开始,否则只需部署您的代码 ;)
我修复了所有迁移,现在在 Heroku 服务器上获得了 API 运行。
真正的答案是:尽早部署到Heroku,不要等到在本地机器上完成开发后再部署。
早点部署会早点发现问题,比如我在 SQlite 和 PostgreSQL 之间的迁移差异。
此外,在迁移文件中进行引用时,如果不使用匹配模型和 table 名称,例如author
vs user
,修改迁移文件以在 运行 迁移之前使用 add_foreign_key
。
例如:
class CreateBooks < ActiveRecord::Migration[5.0]
def change
create_table :books do |t|
t.string :title
t.boolean :adult_content
t.references :author, foreign_key: true
t.timestamps
end
end
end
需要成为:
class CreateBooks < ActiveRecord::Migration[5.0]
def change
create_table :books do |t|
t.string :title
t.boolean :adult_content
t.references :author, index: true # this line changed
t.timestamps
end
# new foreign key specifying correct table name and column
add_foreign_key :books, :users, column: :author_id
end
end
从中发现新知识link:
http://sevenseacat.net/2015/02/24/add_foreign_key_gotchas.html
从 SQLite 迁移到 PostgreSQl 以依赖于 heroku。
我有这样的情况,但使用 tables:出勤率、事件和用户。
PG:undifiedTable 错误:关系用户不存在
我解决了这个问题:
本地我运行railsdb:drop-本地删除数据库
- 我有 3 个迁移文件示例
- 2019_11_07_205648_create_attendace
- 2019_11_07_215648_create_events
- 2019_11_07_225648_create_users
我将前两个文件中的日期更改为:
- 2019_11_07_225648_create_users
- 2019_11_07_235648_create_events
- 2019_11_07_245648_create_attendace
所以他们改变了顺序,首先创建了用户 table,我再次创建了数据库和迁移 $rails db:create
rails db:migrate - 在本地工作
在提交后推送到heroku - git推送heroku master
heroku 运行 rails db:migrate
Heroku 打开并完成 - 瞧 - Finito
我有一个 User
模型和一个 Role
模型。当我开始构建应用程序时,我首先创建 User
模型,生成的迁移文件包含对角色的引用:
class CreateUsers < ActiveRecord::Migration[5.0]
def change
create_table :users do |t|
t.string :first_name
t.string :last_name
t.string :username
t.string :email
t.string :password
t.string :password_digest
t.boolean :banned
t.references :role, foreign_key: true
t.timestamps
end
end
end
然后我创建了生成此迁移文件的 Role
模型:
class CreateRoles < ActiveRecord::Migration[5.0]
def change
create_table :roles do |t|
t.string :title
t.integer :access_level
t.timestamps
end
end
end
我正在尝试使用以下命令 heroku run rails db:migrate
(使用 Rails 5)根据文档部署到 Heroku 并迁移我的数据库。
我从 Heroku 收到一条错误消息:
heroku run rake db:migrate
Running rake db:migrate on ⬢ gentle-headland-79177... up, run.9293 (Free)
D, [2016-12-31T08:15:33.131367 #4] DEBUG -- : (90.7ms) CREATE TABLE "schema_migrations" ("version" character varying PRIMARY KEY)
D, [2016-12-31T08:15:33.152682 #4] DEBUG -- : (11.5ms) CREATE TABLE "ar_internal_metadata" ("key" character varying PRIMARY KEY, "value" character varying, "created_at" timestamp NOT NULL, "updated_at" timestamp NOT NULL)
D, [2016-12-31T08:15:33.155373 #4] DEBUG -- : (1.1ms) SELECT pg_try_advisory_lock(6845940114126317925);
D, [2016-12-31T08:15:33.172106 #4] DEBUG -- : ActiveRecord::SchemaMigration Load (1.2ms) SELECT "schema_migrations".* FROM "schema_migrations"
I, [2016-12-31T08:15:33.178453 #4] INFO -- : Migrating to CreateUsers (20161117083901)
D, [2016-12-31T08:15:33.181903 #4] DEBUG -- : (0.9ms) BEGIN
== 20161117083901 CreateUsers: migrating ======================================
-- create_table(:users)
D, [2016-12-31T08:15:33.199351 #4] DEBUG -- : (13.4ms) CREATE TABLE "users" ("id" serial primary key, "first_name" character varying, "last_name" character varying, "username" character varying, "email" character varying, "password" character varying, "password_digest" character varying, "banned" boolean, "role_id" integer, "created_at" timestamp NOT NULL, "updated_at" timestamp NOT NULL, CONSTRAINT "fk_rails_642f17018b"
FOREIGN KEY ("role_id")
REFERENCES "roles" ("id")
)
D, [2016-12-31T08:15:33.200707 #4] DEBUG -- : (1.0ms) ROLLBACK
D, [2016-12-31T08:15:33.202190 #4] DEBUG -- : (1.2ms) SELECT pg_advisory_unlock(6845940114126317925)
rake aborted!
StandardError: An error has occurred, this and all later migrations canceled:
PG::UndefinedTable: ERROR: relation "roles" does not exist
: CREATE TABLE "users" ("id" serial primary key, "first_name" character varying, "last_name" character varying, "username" character varying, "email" character varying, "password" character varying, "password_digest" character varying, "banned" boolean, "role_id" integer, "created_at" timestamp NOT NULL, "updated_at" timestamp NOT NULL, CONSTRAINT "fk_rails_642f17018b"
FOREIGN KEY ("role_id")
REFERENCES "roles" ("id")
)
据我了解,Heroku 似乎希望先定义 Role
,然后再定义 User
。
为什么在我的本地机器上,我可以 db:migrate 正常,但在 Heroku 上却失败了?
Sqlite3 和 Postgresql 之间的区别?
我该如何解决这个部署问题?
我是否只是将我的 create_role 迁移文件重命名为具有比 create_user 迁移文件更早的时间戳?这甚至是推荐的做法吗? :D
更新
我将我的存储库 git 克隆到我的 iMac 上的桌面文件夹。
然后我 运行 rails db:migrate
在那个新的本地副本上。
没有任何错误。所有数据库迁移 运行、所有 table 以及所有关系都已到位。 Heroku 端确实有些问题。
更新 2
再次将我的存储库签出到一个新的桌面文件夹中,运行 bundle install
然后尝试了这个版本的 db:migrate 命令:
rails db:migrate RAILS_ENV=production
我看到关于角色不存在的相同错误输出
然而
然后我创建了一个 b运行d 全新的 rails 项目 honey
:
rails new honey
做过bundle install
然后去了:
rails generate model User name:string role:references
最后,我去了:
rails db:migrate RAILS_ENV=production
没有错误...
我显然没有生成任何 Role
模型,为什么它没有失败?
这是控制台日志:
Warlocks-iMac:bad clementwu$ cd honey/
Warlocks-iMac:honey clementwu$ ls
Gemfile Rakefile config lib test
Gemfile.lock app config.ru log tmp
README.md bin db public vendor
Warlocks-iMac:honey clementwu$ rails generate model User name:string role:references
Running via Spring preloader in process 27200
Expected string default value for '--jbuilder'; got true (boolean)
invoke active_record
create db/migrate/20170101100613_create_users.rb
create app/models/user.rb
invoke test_unit
create test/models/user_test.rb
create test/fixtures/users.yml
Warlocks-iMac:honey clementwu$ rails db:migrate RAILS_ENV=production
== 20170101100613 CreateUsers: migrating ======================================
-- create_table(:users)
-> 0.0018s
== 20170101100613 CreateUsers: migrated (0.0018s) =============================
Warlocks-iMac:honey clementwu$
数据库已创建,甚至显示 role_id
外键,尽管我的生产数据库中没有 table 调用 role
:
莫名其妙:D
更新 3
也许这是sqlite3数据库和postgresql数据库的区别。
默认情况下,rails 应用程序 config/database.yml
指定生产数据库称为 db/production.sqlite3
,即它不使用 PostgreSQL 数据库,因此它不提供关于角色不存在的错误。
根据这个 Whosebug post:Does SQLite support referential integrity?
看来 SQLite3 没有保证运行引用完整性:(
屁股很痛。
幸好这只是个人学习项目,不是工作项目。
从 PostgreSQL 开始也不太可行,您不能像使用 SQLite3 和 Rails CLI 那样轻松地删除和重新创建数据库。
我想这里要吸取的教训是认真思考并首先创建依赖项 table。
Do I just rename my create_role migration file to have an earlier timestamp than the create_user migration file? Is that even recommended practice ? :D
是的,你的情况没问题。
但是 请记住,当您从一开始就搭建系统时,这样做是可以的。拥有生产数据库后,您应该确保迁移 运行 在部署之前成功。
所以这只是对未来的提示,这里是我自己的生产部署最佳实践
转储您的生产数据库。你可以用
pg_dump <db_name> > <dump_file>; scp <server>:<path_to_dump_file> ./
或https://github.com/sgruhier/capistrano-db-tasks
如果是 heroku,这里很好 article
在本地环境中应用
psql <db_name> < <dump_file>
尝试运行迁移
如果一切出错,请转到第 5 步,否则转到第 6 步
修复迁移问题转到步骤 4
检查迁移是否不会损坏数据,如果它尝试修复迁移并从第 2 步开始,否则只需部署您的代码 ;)
我修复了所有迁移,现在在 Heroku 服务器上获得了 API 运行。
真正的答案是:尽早部署到Heroku,不要等到在本地机器上完成开发后再部署。
早点部署会早点发现问题,比如我在 SQlite 和 PostgreSQL 之间的迁移差异。
此外,在迁移文件中进行引用时,如果不使用匹配模型和 table 名称,例如author
vs user
,修改迁移文件以在 运行 迁移之前使用 add_foreign_key
。
例如:
class CreateBooks < ActiveRecord::Migration[5.0]
def change
create_table :books do |t|
t.string :title
t.boolean :adult_content
t.references :author, foreign_key: true
t.timestamps
end
end
end
需要成为:
class CreateBooks < ActiveRecord::Migration[5.0]
def change
create_table :books do |t|
t.string :title
t.boolean :adult_content
t.references :author, index: true # this line changed
t.timestamps
end
# new foreign key specifying correct table name and column
add_foreign_key :books, :users, column: :author_id
end
end
从中发现新知识link:
http://sevenseacat.net/2015/02/24/add_foreign_key_gotchas.html
从 SQLite 迁移到 PostgreSQl 以依赖于 heroku。
我有这样的情况,但使用 tables:出勤率、事件和用户。
PG:undifiedTable 错误:关系用户不存在
我解决了这个问题:
本地我运行railsdb:drop-本地删除数据库
- 我有 3 个迁移文件示例
- 2019_11_07_205648_create_attendace
- 2019_11_07_215648_create_events
- 2019_11_07_225648_create_users
我将前两个文件中的日期更改为:
- 2019_11_07_225648_create_users
- 2019_11_07_235648_create_events
- 2019_11_07_245648_create_attendace
所以他们改变了顺序,首先创建了用户 table,我再次创建了数据库和迁移 $rails db:create rails db:migrate - 在本地工作
在提交后推送到heroku - git推送heroku master
heroku 运行 rails db:migrate
Heroku 打开并完成 - 瞧 - Finito