将Rails变量设置为不同的Capistrano环境的不同值

时间:2014-02-17 21:41:03

标签: ruby-on-rails ruby-on-rails-3 environment-variables capistrano

我有一个rails应用程序,它设置为使用Capistrano部署到两个不同服务器之一(取决于用户选择部署到哪个)。我想为rails app创建一个环境变量,该变量根据部署网站的服务器而变化。

在我的Capistrano部署(config / deploy.rb)文件中,我有一个变量“阶段”,它有两个供用户部署的选项:

set :stages, %w(production staging)

我试图在我的环境(config / environment.rb)文件的if语句中使用此变量来设置变量,如下所示:

if (:stages == "staging")
    ENV['GLOBAL_EMAIL'] = "email1@domain.com"
else
    ENV['GLOBAL_EMAIL'] = "email2@domain.com"
end

但是,当我测试它时,rails无法呈现#{ENV['GLOBAL_EMAIL']}(据我所知,因为该变量未设置或无法访问。

我的问题是,是否存在以下原因:无法访问阶段,以及是否有根据环境设置变量的方法/更好方法?

请注意,即使一个称为staging,一个称为production,两个环境都部署rails的生产环境(不是rails的测试和生产环境),因此我无法进行测试以查看正在运行的环境rails设置变量。

2 个答案:

答案 0 :(得分:3)

对于初学者,您试图将符号与字符串等同,该字符串将始终返回false。

同样在capistrano中,为了获得您在部署中的环境,您需要stage变量。此变量仅在加载后可用,而不是在ruby读取文件时可用。这意味着你需要提供一个延迟加载的块。问题是这些是在设置局部变量(例如deploy_to

)的上下文中进行评估的
set(:deploy_to) { "/var/www/#{application}/#{stage}" }

这是我的部署脚本中的常见设置,其中将暂存和生产部署到同一服务器。

您可以尝试类似:

set(:global_email) do
  if stage == 'production'
    ENV['GLOBAL_EMAIL'] = 'email1@example.com'
  else
    ENV['GLOBAL_EMAIL'] = 'email2@example.com'
  end
end

或者另一种处理方法是使用特定于部署阶段的文件。

# config/deploy/production.rb
ENV['GLOBAL_EMAIL'] = 'email1@example.com'

# config/deploy/staging.rb
ENV['GLOBAL_EMAIL'] = 'email2@example.com'

更新

我没有注意到提到Rails中的值的问题。这当然与Rails无关,在初始化Rails时Capistrano配置文件中没有任何设置,因为capistrano实际上只能在开发环境中使用。

执行此操作的正确方法是使用rails initalizer并在Rails启动时设置变量。

# config/initializer/global_email.rb

if Rails.env.production?
  GLOBAL_EMAIL = 'email1@example.com'
else
  GLOBAL_EMAIL = 'email2@example.com'
end

答案 1 :(得分:0)

我最终解决的最终解决方案是在每个服务器上创建一个外部来自我的Capistrano部署的文件(例如在/home/[user]/.var/.emails中),其中每个文件只包含所需的电子邮件(例如email1@domain.com)。然后在environments.rb中:

ENV['GLOBAL_EMAIL'] = begin IO.read("/home/[user]/.vars/.email") rescue "" end