我有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结束时真的搞砸了。
我的存储库再次检出新的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$
创建数据库,甚至显示role_id
外键,尽管我的生产数据库中没有名为role
的表:
莫名其妙:D
也许这是sqlite3数据库和postgresql数据库之间的区别。
默认情况下,rails app config/database.yml
指定生产数据库被称为db/production.sqlite3
,即它不使用PostgreSQL数据库,因此它不会给出关于不存在的角色的错误。
根据此Stackoverflow帖子:Does SQLite support referential integrity?
似乎SQLite3不保证参照完整性:(
屁股上的主要疼痛。
这是一件好事,这只是一个个人学习项目,而不是一个工作项目。
从PostgreSQL开始也不太可行,您不能像使用SQLite3和Rails CLI那样轻松地删除和重新创建数据库。
我想在这里要学到的教训是努力思考并首先创建依赖表。
答案 0 :(得分:0)
我是否只是将create_role迁移文件重命名为比create_user迁移文件更早的时间戳?这甚至是推荐的做法吗? :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开始,否则只需部署代码;)
答案 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错误:关联用户不存在
我解决了这个问题:
我在本地运行 rails db:drop -在本地删除数据库
我将前2个文件中的日期更改为:
因此他们更改了顺序,首先创建了用户表,我创建了数据库,然后再次迁移$ rails db:create rails db:migrate -在本地工作
提交后推送到heroku- git push heroku master
heroku run rails db:migrate
Heroku打开并完成-Voila-Finito