Rails:’schema.rb’中的版本号是否用于任何东西?

既然Rails已经对时间戳进行了迁移 ,那么/db/schema.rb顶部的单个版本号似乎毫无意义。 在处理多个开发人员或多个分支时,有时版本号最终不正确。

Rails是否甚至利用了:version参数?

它是否有任何不正确的错误(如:它不反映最近应用的提交的时间戳)?

例:

 ActiveRecord::Schema.define(:version => 20100417022947) do # schema definition ... end 

实际上,版本比这更重要。 您引用的代码实际上只是assume_migrated_upto_version所做的一小部分。 迁移版本的真正效果是假定已经运行所有先前的迁移 (如db / migrate目录中所示) (所以是的,它完成了函数名称的建议。)

这有一些有趣的含义,特别是在多人同时提交新迁移的情况下。

如果您对schema.rb进行版本控制(这是Rails团队推荐的那样),那么你没问题。 您100%保证有冲突(架构版本),并且提交/合并用户必须通过合并其更改并将:version设置为两者中的最高版本来解决它。 希望他们能正确合并。

有些项目选择通过保持schema.rb不受版本控制来避免这种持续的冲突问题。 它们可能仅依赖于迁移,或者保留其偶尔更新的模式的单独版本控制副本。

如果有人在schema.rb的版本之前创建带时间戳的迁移,则会出现此问题。 如果您使用db:migrate,您将应用他们的迁移,您的schema.rb将被更新(但保留相同,更高版本),一切都很好。 但是如果你碰巧遇到db:schema:load(或db:reset),你不仅会错过他们的迁移,而且assume_migrated_upto_version会将他们的迁移标记为已经应用。

此时最好的解决方案可能是要求用户将其迁移的时间戳重新加到合并时。

理想情况下,我更愿意,如果schema.rb实际上包含一个应用的迁移数列表,而不是一个假设到这里:版本。 但我怀疑这会发生–Rails团队似乎相信通过检查schema.rb文件可以充分解决问题。

我决定调查自己。 事实certificate,由于时间戳迁移,Rails对该数字做的唯一事情假设已经应用了具有该特定时间戳的迁移,因此如果不存在则在schema_migration表中创建适当的条目。

来自: /lib/active_record/connection_adapters/abstract/schema_statements.rb

 def assume_migrated_upto_version(version, migrations_path = ActiveRecord::Migrator.migrations_path) # other code ... unless migrated.include?(version) execute "INSERT INTO #{sm_table} (version) VALUES ('#{version}')" end # ...