Rails 5为什么在模式文件中添加nextval方法? [英] Why is rails 5 adding nextval method in schema file?

查看:72
本文介绍了Rails 5为什么在模式文件中添加nextval方法?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

升级到Rails 5后,运行db:migrate时,我的模式文件不断更改。 Rails正在更改:

  create_table flightlessons,强制::cascade do | t | 

至:

  create_table flightlessons,id ::整数,默认值:-> { nextval(’lessons_id_seq':: regclass)},强制::cascade do | t | 

它仅在此型号上出现。为什么Rails在此特定模型上实现nextval?而且,为什么会导致模型名称错误(lessons_id_seq应该是flightlessons_id_seq)。但是,手动将其更改为flightlessons_id_seq会导致相同的无关联错误。

  PG :: UndefinedTable:错误:关系 lessons_id_seq 不存在

要继续,我只需将schema.rb文件改回该行,应该。然后,我可以迁移或测试:进行准备或进行任何操作,直到下次rails将其更改为使用nextval方法为止。



感谢您对此的任何见识。

p>

解决方案

答案很长,因此将其分为几部分。

我的理论



我的猜测是您的开发数据库确实存在包含 lessons_id_seq 序列,并且其 flightlessons.id 的定义取决于该序列(即确切地Rails将放入您的模式文件中。



如何以及为什么?您可能在过去的某个时候将教训表重命名为,但是重命名并没有改变顺序该表所依赖的-并且因为 schema.rb 不会记录序列,所以 lessons_id_seq 序列不会复制到测试数据库中,因此会出现此错误。



要验证我的理论,请运行 rails db 并尝试以下命令:

  \d lessons_id_seq 

这应该返回该序列的定义。然后,尝试:

  \d飞行课程

然后查看 id 列的定义。我希望它包含 DEFAULT nextval('lessons_id_seq')



修复



最简单的解决方法是切换到使用 structure.sql 而不是 schema.rb (请参见文档)。这将保留您数据库的确切状态,并避免Rails的任何干扰或解释,这是造成当前问题的原因。对于生产系统,我总是建议使用 structure.sql



但是,您也可以进入开发数据库并进行更改序列名称:

  ALTER SEQUENCE lessons_id_seq重命名为flightlessons_id_seq; 
ALTER TABLE飞行课程ALTER COLUMN ID设置默认值nextval(’flightlessons_id_seq');

这在生产系统上是一个糟糕的主意,但是如果您的问题只是本地的,应该使用 schema.rb 纠正当前的数据库状态,从而解决当前的问题。如果希望 rails db:drop db:create db:migrate 在新的应用程序上运行,则可能希望将其编码为迁移。



为什么?



Rails放弃默认值的行为您的表的主键可能是Rails 5中的新功能。以前,Rails可能只是相信您的ID列具有合理的默认值,并且忽略了它实际看到的任何值。但是我还没有做过研究来确定这是否正确。


After upgrading to Rails 5 my schema file keeps getting altered when running db:migrate. Rails is changing:

create_table "flightlessons", force: :cascade do |t|

to:

create_table "flightlessons", id: :integer, default: -> { "nextval('lessons_id_seq'::regclass)" }, force: :cascade do |t|

It only occurs on this one model. Why is rails implementing nextval on this particular model? And, why is it getting the model name wrong (lessons_id_seq should be flightlessons_id_seq). Manually changing it to flightlessons_id_seq, however, results in the same no relation error.

PG::UndefinedTable: ERROR:  relation "lessons_id_seq" does not exist

To proceed, I simply alter the schema.rb file back to what that line 'should' be. Then, I can migrate or test:prepare or whatever until the next time rails alters it back to using the nextval method.

Thank you for any insight into this.

解决方案

This is a bit long of an answer, so I've broken it into sections. Buckle up!

My theory

My guess is that your development database does contain the lessons_id_seq sequence, and that its definition of flightlessons.id is set to depend on it (i.e., exactly what Rails is putting into your schema file).

How and why? You likely renamed the lessons table to flightlessons at some point in the past, but that rename didn't change the sequence that the table depended on -- and since schema.rb does not record sequences, the lessons_id_seq sequence does not get copied to your test database, and thus you get this error.

To verify my theory, run rails db and try the following commands:

\d lessons_id_seq

This should return the definition of that sequence. Then, try:

\d flightlessons

And look at the definition of the id column. I expect it to include DEFAULT nextval('lessons_id_seq').

Fixes

The easiest way to fix this is to switch to using structure.sql instead of schema.rb (see the docs). This will carry over the exact state of your database and avoid any interference or interpretation by Rails, which is what's causing your current issue. I always recommend structure.sql for production systems.

However, you can also go into your development database and change the sequence name:

ALTER SEQUENCE lessons_id_seq RENAME TO flightlessons_id_seq;
ALTER TABLE flightlessons ALTER COLUMN id SET DEFAULT nextval('flightlessons_id_seq');

This would be a terrible idea on a production system, but if your issue is just local, it should rectify your current database state with your schema.rb and thus address your current problem. You may wish to encode that into a migration, if you want rails db:drop db:create db:migrate to work on a fresh app.

Why now?

The behavior where Rails is dumping out the default value for your table's primary key may very well be new in Rails 5. Previously, Rails may have just trusted that your ID column had a sane default, and ignored whatever value it actually saw. But I haven't done the research to see if that's true or not.

这篇关于Rails 5为什么在模式文件中添加nextval方法?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆