db:migrate:reset不适用于环境变量

时间:2014-10-22 16:15:58

标签: ruby-on-rails postgresql rake

我设置环境变量的方式与概述here一样。

换句话说,我创建了一个config / app_env_vars.rb文件并放入:

unless Rails.env.production?
  ENV['DB_PASSWORD'] = 'password'
  ENV['DB_USERNAME'] = 'username'
end
puts 'ECHO app_env_vars.rb'

在config / environment.rb中我放了:

app_env_vars = File.join(Rails.root, 'config', 'app_env_vars.rb')
load(app_env_vars) if File.exists?(app_env_vars)

puts "ECHO environment.rb"

Rails.application.initialize!之前

在database.yml中:

development:
  adapter: postgresql
  encoding: unicode
  database: my_app_development
  host: localhost
  pool: 5
  password: <%= ENV['DB_PASSWORD'] %>

test:
  adapter: postgresql
  encoding: unicode
  database: my_app_test
  host: localhost
  pool: 5
  password: <%= ENV['DB_PASSWORD'] %>

当我运行bundle exec rake db:migratebundle exec rake db:reset等任务时,它运行正常,但当我运行bundle exec rake db:migrate:reset时,它将无法显示:

fe_sendauth: no password supplied
.
.
.
Couldn't drop my_app_development
fe_sendauth: no password supplied
.
.
.
Couldn't drop my_app_test
fe_sendauth: no password supplied
ECHO app_env_vars.rb
ECHO environment.rb

通常当我运行bundle exec rake db:migrate(和db:drop)时,它将首先显示ECHO部分,然后执行任务并输出日志。但是在db:migrate:reset的情况下,它不会在任务完成之前初始化环境变量。

当在database.yml中时,我把实际的密码而不是env变量放在那里 db:migrate:reset没有问题。

这是rake db:migrate:reset with --trace option

** Invoke db:migrate:reset (first_time)
** Invoke db:drop (first_time)
** Invoke db:load_config (first_time)
** Execute db:load_config
** Execute db:drop
fe_sendauth: no password supplied
.
. # gem trace stuff...
.
Couldn't drop my_app_development
fe_sendauth: no password supplied
.
. # gem trace stuff...
.
Couldn't drop my_app_test
** Invoke db:create (first_time)
** Invoke db:load_config 
** Execute db:create
fe_sendauth: no password supplied
.
. # gem trace stuff...
.
Couldn't create database for {"adapter"=>"postgresql", "encoding"=>"unicode", "database"=>"my_app_development", "host"=>"localhost", "pool"=>5, "password"=>nil}
fe_sendauth: no password supplied
.
. # gem trace stuff...
.
Couldn't create database for {"adapter"=>"postgresql", "encoding"=>"unicode", "database"=>"my_app_test", "host"=>"localhost", "pool"=>5, "password"=>nil}
** Invoke db:migrate (first_time)
** Invoke environment (first_time)
** Execute environment
ECHO app_env_vars.rb
ECHO environment.rb
** Invoke db:load_config 
** Execute db:migrate
** Invoke db:_dump (first_time)
** Execute db:_dump
** Invoke db:schema:dump (first_time)
** Invoke environment 
** Invoke db:load_config 
** Execute db:schema:dump
** Execute db:migrate:reset

这是rake db:reset

的--trace
** Invoke db:reset (first_time)
** Invoke environment (first_time)
** Execute environment
ECHO app_env_vars.rb
ECHO environment.rb
** Invoke db:load_config (first_time)
** Execute db:load_config
** Execute db:reset
** Invoke db:drop (first_time)
** Invoke db:load_config 
** Execute db:drop
** Invoke db:setup (first_time)
** Invoke db:schema:load_if_ruby (first_time)
** Invoke db:create (first_time)
** Invoke db:load_config 
** Execute db:create
** Invoke environment 
** Execute db:schema:load_if_ruby
** Invoke db:schema:load (first_time)
** Invoke environment 
** Invoke db:load_config 
** Execute db:schema:load
-- enable_extension("plpgsql")
   -> 0.0772s
-- create_table("users", {:force=>true})
   -> 0.0795s
-- add_index("users", ["email"], {:name=>"index_users_on_email", :unique=>true, :using=>:btree})
   -> 0.0406s
-- initialize_schema_migrations_table()
   -> 0.0829s
** Invoke db:structure:load_if_sql (first_time)
** Invoke db:create 
** Invoke environment 
** Execute db:structure:load_if_sql
** Invoke db:seed (first_time)
** Execute db:seed
** Invoke db:abort_if_pending_migrations (first_time)
** Invoke environment 
** Execute db:abort_if_pending_migrations
** Execute db:setup

如果db:reset ** Execute environment部分在执行任务之前完成,而db:migrate:reset ** Execute environment则在执行几次后完成

1 个答案:

答案 0 :(得分:0)

这种设置(在文件中设置env变量然后通过environment.rb加载它们)不起作用的原因是因为活动记录可以在rails之外使用,因此现在每个任务都使用初始化的rails环境运行。

更好的解决方案是使用figarodot-env等宝石,这些宝石将加载每个rake任务。我对这些宝石究竟是怎么做的我不确定但如果我进入它并发现我会在这里发布。