Rails:'schema.rb'中的版本号是用于什么的吗?

Dan*_*ley 23 database migration ruby-on-rails

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

Rails甚至:version不再使用该参数了吗?

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

例:

ActiveRecord::Schema.define(:version => 20100417022947) do
  # schema definition ...
end
Run Code Online (Sandbox Code Playgroud)

小智 33

实际上,版本比这更重要.您引用的代码实际上只是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文件可以充分解决问题.

  • 我不确定这个答案过去是否正确,但看起来已经不是了.http://guides.rubyonrails.org/migrations.html#what-s-in-a-name中的名称部分中的内容清楚地表明Rails将尝试运行尚未运行的任何迁移. ..即使后来创建的迁移已经运行. (4认同)

Dan*_*ley 5

我决定调查自己.事实证明,由于带时间戳的迁移,Rails对该数字做的唯一事情假设已经应用了具有该特定时间戳的迁移,因此如果schema_migration表不存在则在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
    # ...
Run Code Online (Sandbox Code Playgroud)