为什么rails 5在模式文件中添加nextval方法?
升级到Rails 5后,我的架构文件在运行db:migrate时不断被更改。 Rails正在发生变化:
create_table "flightlessons", force: :cascade do |t|
至:
create_table "flightlessons", id: :integer, default: -> { "nextval('lessons_id_seq'::regclass)" }, force: :cascade do |t|
它只发生在这一个模型上。 为什么rails在这个特定型号上实现nextval? 而且,为什么它的模型名称错误(lessons_id_seq应该是flightlessons_id_seq)。 但是,手动将其更改为flightlessons_id_seq会导致相同的无关系错误。
PG::UndefinedTable: ERROR: relation "lessons_id_seq" does not exist
为了继续,我只需将schema.rb文件更改回该行应该是什么。 然后,我可以迁移或测试:准备或其他什么,直到下一次rails将其改回使用nextval方法。
感谢您对此的任何见解。
这有点长的答案,所以我把它分成了几个部分。 系好安全带!
我的理论
我的猜测是你的开发数据库确实包含了lessons_id_seq
序列,并且它的flightlessons.id
定义被设置为依赖于它(即,确切地说Rails放入你的模式文件中)。
怎么样和为什么? 您可能在过去的某个时刻将lessons
表重命名为flightlessons
,但重命名并未更改表所依赖的顺序 – 并且由于schema.rb
不记录序列,所以lessons_id_seq
序列不会复制到您的测试数据库,从而得到此错误。
要validation我的理论,请运行rails db
并尝试以下命令:
\d lessons_id_seq
这应该返回该序列的定义。 然后,尝试:
\d flightlessons
并查看id
列的定义。 我希望它包含DEFAULT nextval('lessons_id_seq')
。
修复
解决此问题的最简单方法是切换到使用structure.sql
而不是schema.rb
(请参阅文档 )。 这将inheritance数据库的确切状态,避免Rails的任何干扰或解释,这是导致您当前问题的原因。 我总是推荐用于生产系统的structure.sql
。
但是,您也可以进入开发数据库并更改序列名称:
ALTER SEQUENCE lessons_id_seq RENAME TO flightlessons_id_seq; ALTER TABLE flightlessons ALTER COLUMN id SET DEFAULT nextval('flightlessons_id_seq');
这对于生产系统来说是一个糟糕的想法,但如果您的问题只是本地问题,它应该使用schema.rb
纠正您当前的数据库状态,从而解决您当前的问题。 您可能希望将其编码为迁移,如果您需要rails db:drop db:create db:migrate
以在新应用程序上运行。
为什么现在?
在Rails 5中,Rails倾销出表的主键的default
值的行为可能是新的。以前,Rails可能只是相信你的ID列有一个合理的默认值,并忽略它实际看到的任何值。 但我还没有做过研究,看看这是不是真的。
- Rails 5 db migration:如何修复ActiveRecord :: ConcurrentMigrationError
- Rails:从MySQL转换为PostGres打破了Geokit距离计算?
- “运行rspec时,无法在任何源中找到pg-0.12.2”
- Rails:部署到Heroku,有很多问题
- 如何覆盖Ruby Ranges的..和…运算符以接受Float :: INFINITY?
- 在Heroku,Cedar,与Unicorn:获取ActiveRecord :: StatementInvalid:PGError:SSL SYSCALL错误:检测到EOF
- 将数组值发送到ruby中的sql查询?
- Rails迁移:PostgreSQL上的Bigint似乎失败了吗?
- 在不同的服务器上使用Rails的postgresql COPY命令的问题