运行两次 rake db tasks

9
我在使用Faker向开发的Postgres数据库中播种数千个记录时,发现了种子文件的问题。我中止了播种操作并回滚了插入,修复了seeds.rb文件。
当我再次运行它时,每个rake db:*任务都会运行两次。我可以正常运行rake routes,但如果我运行rake db:drop,就会得到类似以下的结果:
$ rake db:drop
Dropped database 'vp_development'
Dropped database 'vp_development'

如果我尝试运行迁移,当它尝试应用索引时整个过程都会崩溃,因为它已经创建了那些列。
我只有一个默认的Rakefile,在lib或其他任何地方都没有自定义的rake文件。
环境是rails 5.0.0.1和ruby 2.2.2,如果这有任何区别的话。 我现在感到非常迷失。
这是我的Rakefile。
# Add your own tasks in files placed in lib/tasks ending in .rake,
# for example lib/tasks/capistrano.rake, and they will automatically be available to Rake.

require_relative 'config/application'

Rails.application.load_tas

我看到其他帖子建议这可能是一个gem的问题,但是当这个问题开始时,我已经几天没有添加新的gem了。无论如何,这里是gemfile。

source 'https://rubygems.org'


# Bundle edge Rails instead: gem 'rails', github: 'rails/rails'
gem 'rails', '~> 5.0.0', '>= 5.0.0.1'
gem 'puma', '~> 3.0'
gem 'sass-rails', '~> 5.0'
gem 'uglifier', '>= 1.3.0'
gem 'coffee-rails', '~> 4.2'
gem 'jquery-rails'
gem 'turbolinks', '~> 5'
gem 'jbuilder', '~> 2.5'
gem 'devise'
gem 'bootstrap-sass', '3.3.6'
gem 'pg'
gem 'friendly_id'
gem 'will_paginate'
gem 'faker'

group :development, :test do
  #gem 'sqlite3'
  gem 'byebug', platform: :mri
end

group :development do
  gem 'web-console'
  gem 'listen', '~> 3.0.5'
  gem 'spring'
  gem 'spring-watcher-listen', '~> 2.0.0'
end

group :production do
end

# Windows does not include zoneinfo files, so bundle the tzinfo-data gem
gem 'tzinfo-data', platforms: [:mingw, :mswin, :x64_mingw, :jruby]

编辑:我还尝试了在db命名空间中使用自定义任务,它可以正常工作。 只运行一次。 据我所知,db:drop,db:create,db:reset,db:migrate是唯一运行两次的任务。 下面是 db:drop 的跟踪信息和另一个 db:create 的跟踪信息。

 $ rake db:drop --trace
** Invoke db:drop (first_time)
** Invoke db:load_config (first_time)
** Execute db:load_config
** Invoke db:check_protected_environments (first_time)
** Invoke environment (first_time)
** Execute environment
** Invoke db:load_config 
** Execute db:check_protected_environments
** Execute db:drop
** Invoke db:drop:_unsafe (first_time)
** Invoke db:load_config 
** Execute db:drop:_unsafe
Dropped database 'vp_development'
Dropped database 'vp_development'

rake db:create --trace
** Invoke db:create (first_time)
** Invoke db:load_config (first_time)
** Execute db:load_config
** Execute db:create
Created database 'vp_development'
Database 'vp_development' already exists

这有帮助吗? - Doon
我之前确实经历过这个问题,但我尝试从Rakefile运行他们的自定义任务,结果完美解决了。只运行了一次,所以不能是和他们相同的原因。$ rake foo:bar 正在运行 仍在运行$ rake db:bar 正在运行 仍在运行 - bubunt205
2个回答

7
我找到了罪魁祸首。在最近的几个git提交中,我的database.yml不知何故被复制了一份。
每次我尝试运行任何引用环境的rake命令时,它都会运行两次。这是一个非常奇怪的问题。很高兴我能够解决它。

5
我有过类似的情况。我不知道为什么我的结构负载会因为重复的条目而失败。结果发现 rails db:structure:load(以及我认为所有其他的 db: 任务)会遍历 database.yml 中列出的每个数据库,而不仅仅是开发环境中的一个。我的数据库在 test 中被复制了。我想我不能这样做 :) - David Dombrowsky
@DavidDombrowsky 天啊,这正是我的问题所在。这对我来说似乎是一个明显的错误!谢谢,我真的很困惑。 - mecampbellsoup
2
我也遇到了同样的问题,因为我从环境变量中提取数据库名称,例如 database: <%= ENV["MYSQL_DATABASE"] %>,所以所有的环境都使用相同的数据库,即使在指定 RAILS_ENV RAILS_ENV=development rake db:drop 时也是如此。 - spyle

2

我想详细说明一下被接受的答案。

当你运行db:schema:load时,Rails内部的Rake任务定义最终调用了ActiveRecord::Tasks::DatabaseTasks.load_schema_current()这在这里发生

在该任务内部,它调用了一个内部方法each_current_config

该方法循环遍历每个环境productiondevelopment等),并将该环境的数据库配置传递给block

如您所见,如果环境是development,它会自动将test作为一个环境添加进去。这是为了方便,以便在本地设置test数据库。如果您的developmenttest数据库使用相同的数据库名称,则会尝试创建/加载相同的数据库两次(并可能在第二个数据库上遇到错误)。

您有几个选项可以避免这种情况:

  1. 您可以设置SKIP_TEST_DATABASE=1,这将跳过创建test
  2. 您可以指定DATABASE_URL(而不是单独的数据库组件),这将跳过创建test
  3. 您可以为每个环境提供唯一的数据库名称,这应该避免冲突并允许您创建developmenttest
default: &default
  adapter: postgresql
  encoding: unicode
  host: <%= ENV.fetch('POSTGRES_HOST', 'localhost') %>
  port: <%= ENV.fetch('POSTGRES_PORT', 5432) %>
  username: <%= ENV.fetch('DATABASE_USERNAME', 'postgres') %>
  password: <%= ENV.fetch('DATABASE_PASSWORD', '') %>
  pool: <%= ENV.fetch('DATABASE_CONNECTION_POOL', 5) %>
  timeout: <%= ENV.fetch('DATABASE_TIMEOUT', 5000) %>

test: &test
  <<: *default
  min_messages: warning
  database: <%= ENV.fetch('DATABASE_NAME', 'foo_test') %>

development:
  <<: *default
  database: <%= ENV.fetch('DATABASE_NAME', 'foo_development') %>

staging:
  <<: *default

production:
  <<: *default

这些信息应该真的与被接受的答案一起提供。谢谢。 - niborg

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接