mysql - Rails:minitest是否使用schema.rb重新创建测试模式?

标签 mysql ruby-on-rails ruby ruby-on-rails-3 rails-migrations

我试图将一个遗留的rails系统提升到更高的当前标准,但是在让测试数据库反映schema.rb状态以及通过迁移所做的更改时遇到了问题。
tl;dr是否运行rake minitest:all调用与rake db:schema:load相同的代码?
环境
钢轨3.2.20
红宝石1.9.3
微型测试宝石4.6.2
小型钢轨0.5.2
MySQL 5.1版
本地os x,测试和生产linux
原始系统状态
该系统最初是由非软件工程师、不了解rails等的人创建的。添加了一些特定于mysql的类型(例如unsigned int),这些类型不受rails迁移和schema.rb的特别支持。所以系统使用了structure.sql并且对于如何保持更新、签入git等等非常草率。
此外,在稍后的某个时刻,有人决定用包含自生成guid的id替换一些常用的数字、自动递增的主键varchar字段。字段名仍然id,但它是一个新的数据类型。
但是所有的数百个测试(他们确实写了很多测试)都是基于id而不是fixture名称来引用fixture实例的,fixture之间存在依赖关系,等等。他们决定不更新测试,而是使用旧的模式(数字id)进行测试。并使用新的(在id中带有varchar guid)进行生产。
Op深吸一口气…
不同环境的数据库不同步,有数百个迁移,但它们停止工作,因为“开发”数据库是共享的,而且…好吧,你知道,这是一个烂摊子。
我正试图解决所有这些问题,并最终转移到postgresql。
我所做的
我使用RAILS_ENV=production rake db:structure:dump从生产数据库本地转储了模式——这产生了一个权威的structure.sql。我创建了一个新的开发数据库,并使用rake db:structure:load加载了它的模式——我仔细比较了生产和开发模式,它们是相同的,甚至是上面提到的特定于mysql的unsigned int。
我想使用schema.rb有两个原因。首先,我想要一个不依赖mysql的系统。其次,当使用structure.sql时,我们签入一个文件,该文件具有最近运行的db:migrate机器的自动增量值、db设置和其他特性。这可能会产生我希望避免的问题。
因此,我在本地将配置设置从:sql更改为使用:ruby设置生成schema.rb
但是schema.rb确实不喜欢将id字段转换为varchar的想法——我已经确定了所有使用这个declareself.primary_key = :id的模型,然后我创建了一个新的迁移来替换所有旧的迁移,一个“汇总迁移”,其内容主要是newschema.rb,但有几种修改。
特别是,当id字段是guidvarchar时,我这样设置表(从迁移中):

class RolledUpStateAsOf20150403 < ActiveRecord::Migration

  def up

    # ... all other table definitions in the system

    create_table "users", :id => false, :force => false do |t|
      t.string   "id", :limit => 36, :default => "", :null => false
      t.string   "login"
      # and all the other user fields
    end
    execute("ALTER TABLE users ADD PRIMARY KEY (id);")

    #...
  end

  def down
    raise ActiveRecord::IrreversibleMigration
  end
end

所以:
:id => false防止迁移创建正常ID
:force => false以确保此迁移不会对生产数据库造成影响
t.string "id"具有大小和其他主键设置
execute(ALTER TABLE ...)最后声明id为主键
以后每次我创建一个新的迁移时,schema.rb都会被更新——这在现在是不准确的(直到我们以后去掉那些古怪的id字段)。迁移将遵循正常的Rails实践。
一旦生产、登台、开发和其他数据库同步,一切都很好。
除了我们测试的时候。
那么为什么我运行minitest时这不起作用呢?
我用minitest运行测试,如下所示:
RAILS_ENV=test rake db:drop
RAILS_ENV=test rake db:create
RAILS_ENV=test rake db:migrate
RAILS_ENV=test rake minitest:all

但随后我开始看到错误,这些错误是由于id列被定义为int而不是varchar引起的。
如果在运行minitest之前(在dropcreate和我的magic迁移之后)检查模式,那么是正确的:时髦的主键是varchar所需的。
但在测试过程中的某个地方,模式似乎正在被改回rails标准。我可以回去检查id列返回到int的模式。
假设模式是从实际的schema.rb生成的。
这是正常/预期的行为吗?关于如何实现我的目标的任何建议,这些建议很简单:
迁移又起作用了
开发、测试、登台和生产数据库在结构上是相同的
我现在需要使用疯狂的基于guid的字段
如果可能的话,我宁愿不使用varchar

最佳答案

好的,所以我相信以下是正确的:minitest,或者test do rundb:schema:load。或在db:structure:load中运行时RAILS_ENV=test——这可以通过运行rake test --tracerake minitest:all --trace来观察。
因此,由于对名为schema.rb的字段使用varchar而不是int,所以我的id无法完全重新创建数据库。我不得不改用structure.sql
其余的解决方案,包括在第一次“汇总”迁移时添加一个手工修改的schema.rb版本,效果很好,随后的迁移也很好。在将来的某个时候,我将把id转换回它们的自然形式;现在,这是一个合适的解决方案,如果不美观的话。

关于mysql - Rails:minitest是否使用schema.rb重新创建测试模式?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29547518/

相关文章:

PHP "No Database Selected"

mysql - 德鲁帕尔 6 : using too many Views module causing site to go down cos of too many mysql connection

ruby-on-rails - Rails has_many :through and N+1

ruby-on-rails - Ruby:将对象添加到数组的末尾

ruby - 如何查找并返回数组中的重复值

MySQL,通过ID选择一组元素?

mysql - phpBB3.0.9如何正确导入数据库

ruby-on-rails - 安装 RubyPress

ruby-on-rails - 指定方法参数的允许值

ruby - 为什么 Ruby class_eval 从范围中删除常量?