Heroku Rails数据库迁移文件顺序和关系

时间:2016-12-31 08:22:26

标签: ruby-on-rails heroku ruby-on-rails-5 dbmigrate

我有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:迁移正常但是在Heroku上它失败了?

可能是Sqlite3和Postgresql之间的区别?

如何解决此部署问题?

我是否只是将create_role迁移文件重命名为比create_user迁移文件更早的时间戳?这甚至是推荐的做法吗? :d

更新

我将我的存储库的git clone复制到了我的iMac上的Desktop文件夹。

然后我在新的本地副本上运行rails db:migrate

没有任何错误。所有数据库迁移都已运行,所有表都与所有关系一起就位。 Heroku结束时真的搞砸了。

更新2

我的存储库再次检出新的Desktop文件夹,运行bundle install然后尝试了这个版本的db:migrate命令:

rails db:migrate RAILS_ENV=production

我看到关于角色的相同错误输出不存在

无论其

然后我创建了一个品牌打击新的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$ 

screenshot

创建数据库,甚至显示role_id外键,尽管我的生产数据库中没有名为role的表:

db screenshot

莫名其妙:D

更新3

也许这是sqlite3数据库和postgresql数据库之间的区别。

默认情况下,rails app config/database.yml指定生产数据库被称为db/production.sqlite3,即它不使用PostgreSQL数据库,因此它不会给出关于不存在的角色的错误。

根据此Stackoverflow帖子:Does SQLite support referential integrity?

似乎SQLite3不保证参照完整性:(

屁股上的主要疼痛。

这是一件好事,这只是一个个人学习项目,而不是一个工作项目。

从PostgreSQL开始也不太可行,您不能像使用SQLite3和Rails CLI那样轻松地删除和重新创建数据库。

我想在这里要学到的教训是努力思考并首先创建依赖表。

3 个答案:

答案 0 :(得分:0)

  

我是否只是将create_role迁移文件重命名为比create_user迁移文件更早的时间戳?这甚至是推荐的做法吗? :d

是的,你的情况没问题。

但是请记住,当你在一开始就搭建系统时,这样做是可以的。拥有生产数据库后,您应该确保在部署之前成功运行迁移。

所以只是未来的提示,这是我自己的生产部署的最佳实践

  1. 转储您的生产数据库。你可以用

    来做

    pg_dump <db_name> > <dump_file>; scp <server>:<path_to_dump_file> ./

    https://github.com/sgruhier/capistrano-db-tasks

    如果是heroku,那就很好article

  2. 使用

    将其应用于本地环境

    psql <db_name> < <dump_file>

  3. 尝试运行迁移

  4. 如果一切都出错,请转到步骤5,否则转到步骤6

  5. 修复迁移问题转到第4步

  6. 检查迁移是否不会破坏数据,是否尝试修复迁移并从步骤2开始,否则只需部署代码;)

答案 1 :(得分:0)

我修复了所有迁移并立即在Heroku服务器上运行API。

真正的答案是:尽早部署到Heroku,不要等到本地计算机完成开发后再部署。

早期部署会尽早发现问题,例如我在SQlite和PostgreSQL之间的迁移差异。

此外,在迁移文件中进行引用时,如果不使用匹配的模型和表名,例如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

从此链接中找到新知识:

http://sevenseacat.net/2015/02/24/add_foreign_key_gotchas.html

答案 2 :(得分:0)

从SQLite迁移到PostgreSQl以依赖于heroku。

我遇到这样的情况,但是使用表格:出勤,事件和用户。

PG:undifiedTable错误:关联用户不存在

我解决了这个问题:

  1. 我在本地运行 rails db:drop -在本地删除数据库

    • 我有3个迁移文件示例
    • 2019_11_07_ 20 5648_create_attendace
    • 2019_11_07_ 21 5648_create_events
    • 2019_11_07_ 22 5648_create_users
  2. 我将前2个文件中的日期更改为:

    • 2019_11_07_ 22 5648_create_users
    • 2019_11_07_ 23 5648_create_events
    • 2019_11_07_ 24 5648_create_attendace
  3. 因此他们更改了顺序,首先创建了用户表,我创建了数据库,然后再次迁移$ rails db:create rails db:migrate -在本地工作

  4. 提交后推送到heroku- git push heroku master

  5. heroku run rails db:migrate

  6. Heroku打开并完成-Voila-Finito