【问题标题】:db:migrate:reset doesn't work with environment variablesdb:migrate:reset 不适用于环境变量
【发布时间】:2014-12-18 04:20:03
【问题描述】:

我设置环境变量的方式就像在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 选项

** 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 在几次执行之后完成

【问题讨论】:

  • 为什么不用 application.yml 处理环境变量?它开箱即用。
  • 您是说 application.rb 吗?因为我找不到 application.yml。我正在使用 rails 4.1.6 我这样使用它是因为我知道这是“好习惯”,还因为当我上传到 github 时我不希望其他成员看到敏感信息。
  • 据我了解,环境变量是在系统 (os) 中定义的,而不是在应用程序中。您也可以将 'DB_PASSWORD=123 rake db:migrate' 传递给 rake 任务
  • 它们也可以由应用程序定义,或者全部放在一个文件中。感谢您的耙子任务。这个问题的重点是找出为什么 rake db:migrate:reset 的行为与 rake db:reset 不同。

标签: ruby-on-rails postgresql rake


【解决方案1】:

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

更好的解决方案是使用像 figarodot-env 这样的 gem,它们会在每个 rake 任务中加载。我不确定这些宝石到底是如何完成的,但如果我进入它并发现我会在这里发布。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2023-02-02
    • 2019-08-11
    • 2018-10-15
    • 2017-09-16
    • 2021-03-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多