【问题标题】:DatabaseCleaner.clean_with(:truncate) does not reset auto incremented idDatabaseCleaner.clean_with(:truncation) 不会重置自动增量 ID
【发布时间】:2015-06-23 20:02:12
【问题描述】:

我目前在运行 PostgreSQL 的 Rails 项目中使用DatabaseCleaner,并将其设置如下。

RSpec.configure do |config|
  config.before(:suite) do
    DatabaseCleaner.clean_with(:truncation, { pre_count: true, reset_ids: true })
  end

  config.before(:each, js: true) do
    DatabaseCleaner.strategy = :truncation
  end

  config.before(:each) do
    DatabaseCleaner.strategy = :transaction
  end

  config.before(:each) do
    DatabaseCleaner.start
  end

  config.after(:each) do
    DatabaseCleaner.clean
  end
end

在我的一个 Rails 测试套件中,我打印了一个实例的 id。我认为它应该是相对较小的数字,因为 clean_with(:truncate) 假设清除 db 并在其上运行真空。但每次我运行测试时它都会增加。

测试通过了,不管它使用什么顺序。但是为什么clean_with(:truncation) 没有按应有的方式工作?

====== 编辑 ======

这在 RSpec 测试的范围内。我知道序列编号对性能没有影响,但是对每个 :suite 进行昂贵的清理 (:truncation) 并使用便宜且快速的清理 (:transaction) 会。所以我想了解为什么clean_with(:truncation) 在运行测试套件之前不会为我重置 id 以获得干净的数据库状态。

【问题讨论】:

  • @muistooshort 你是对的。我将编辑我的问题。
  • 我不知道 rails,但 truncate 本身不会重置 Postgres 中的任何序列。但是 Postgres 支持truncate .. restart identity。也许在 Rails 中这可以以某种方式配置
  • 选项 reset_ids 假设确保序列重置。实际上。默认情况下,截断重置数据库清理器中的序列。我刚刚添加了该选项以清除自己。如果我做DatabaseCleaner.strategy = :truncate,它会正确重置。但我想为每个使用事务来优化性能
  • 如果你有一个关于你的身份的索引,它们是高还是低都没有关系......你不会因为数字低而获得任何性能提升......
  • @Lichtamberg 对。我了解索引编号与性能无关。但是使用交易策略可以。为每个测试用例运行截断比运行事务慢。这就是为什么我想对每个 :suite 执行截断

标签: ruby-on-rails ruby postgresql rspec-rails database-cleaner


【解决方案1】:

这就是数据库的工作原理。

$ createdb test1
$ psql -d test1

> create table numbers (id serial, x integer);
> insert into numbers (x) values (1), (2), (3);
> select id from numbers order by id desc limit 1;

# 3

> truncate numbers;
> insert into numbers (x) values (1), (2);
> select id from numbers order by id desc limit 1;

# 5

如您所见,:truncate 表示数据库清理器意味着 truncate。希望这是有道理的。

EDIT -- 完全错过了这个问题。

:reset_ids 不起作用的原因是 postgresql 版本低。使用 psql --version 查找您的版本,并从数据库清理器源中查找您需要 8.4 或更高版本。

@restart_identity ||= db_version >=  80400 ? 'RESTART IDENTITY' : ''

我运行的是 9.3.5,运行良好。

> truncate numbers restart identity;
> insert into numbers (x) values (1);
> select * from numbers;

#  id | x 
# ----+---
#   1 | 1

为了确保数据库清理器也能正常工作。

require 'rails/all'
require 'database_cleaner'
ActiveRecord::Base.establish_connection('postgres://localhost/test1')
class Number < ActiveRecord::Base; end
Number.count
# => 1
DatabaseCleaner.clean_with(:truncation, reset_ids: true)

它重置串行列。

$ psql -d test1
> insert into numbers (x) values (1);
> select * from numbers;

#  id | x 
# ----+---
#   1 | 1

【讨论】:

  • 感谢您的回答。但如果您的回答属实,DatabaseCleaner.strategy = :truncation 如何重置索引?我很困惑。 github.com/DatabaseCleaner/… gem 提供了 activerecord 选项来重置我通过的 id 以确保它确实如此。
  • 另外,stackoverflow.com/questions/11419536/… 选择的答案解释说:截断是一种重置序列的方法。可以是特定于数据库版本的吗?
  • 太棒了。让我快速测试一下
  • 如果我在控制台中运行clean_with,它会重置序列。但是当我将它作为 RSpec 测试套件的一部分时,它不会。 postgres 版本是 9.3.3。 DatabaseCleaner gem v1.4.1。 RSpec v3.2.0
  • 您的回答并没有解决我的问题,但如果我在接下来的 24 小时内没有得到任何其他信息,我会将您的回答标记为正确的。非常感谢。
猜你喜欢
  • 2011-03-02
  • 1970-01-01
  • 1970-01-01
  • 2017-01-02
  • 1970-01-01
  • 1970-01-01
  • 2019-05-11
  • 1970-01-01
  • 2014-12-05
相关资源
最近更新 更多