将变量传递给Rails应用程序中的config / environments / demo.rb

时间:2011-10-01 00:02:46

标签: ruby-on-rails ruby model-view-controller runtime metaprogramming

过去几天,我一直在努力解决我正在开发的Ruby on Rails应用程序中遇到的问题。我有不同的国家/地区,我们使用不同的Amazon S3存储桶。 Amazon S3密钥凭证在config / environments / environment_name.rb中存储为常量(例如:demo.rb)我无法确定从配置文件操作的国家/地区。我可以从控制器,模型,视图等确定我们正在操作的国家/地区,但不能从配置文件中确定。是否有Ruby元编程或其他一些我不知道的魔术,所以我想说如果我们在应用程序中作为一个国家在英国工作,使用英国的桶凭据或德国作为国家,请使用德国的桶凭证?我想不出从app本身传递参数到环境文件的方法。非常感谢您提供的所有帮助。

2 个答案:

答案 0 :(得分:0)

您可能应该为每个请求选择相关的凭据,而不是将配置详细信息实际传递给您在启动时使用的S3客户端。您的配置文件可以将它们全部定义为哈希,如下所示:

# config/s3.rb
S3_BUCKETS => { 
  :us => 'our-files-us',
  :gb => 'our-files-gb',
  :tz => 'special-case'
}

然后您可以根据请求选择凭据(可能是您的AppController):

bucket_name = S3_BUCKETS[I18n.locale]
# pass this info to your S3 client

有意义吗?

答案 1 :(得分:0)

如果您想要了解主要应用程序中的每个国家/地区配置,请编写一个小型中间件。

中间件非常简单。无所事事的中间件看起来像这样:

class DoesNothing
  def initialize(app, *args)
    @app = app
  end

  def call(env)
    @app.call(env)
  end
end

Rack通过将一系列中间件链接在一起来为应用程序提供动力......每个中间件都被引用@app,这是链中的下一个链接,它必须在该应用程序上调用#call。链末尾的那个运行应用程序。

所以在你的情况下,你可以在这里做一些额外的配置。

class PerCountryConfiguration
  def initialize(app)
    @app = app
  end

  def call(env)
    case env["COUNTRY"]
      when "AU"
        Rails.application.config.s3_buckets = { ... }
      when "US"
        Rails.application.config.s3_buckets = { ... }
      ... etc        
    end

    @app.call(env)
  end
end

有几种方法可以使用中间件,但由于它依赖于对Rails环境的访问,因此您需要从Rails内部进行操作。把它放在你的application.rb中:

config.middleware.use PerCountryConfiguration

如果要将其他参数传递给中间件的构造函数,只需在类名后面列出:

config.middleware.use PerCountryConfiguration, :some_argument

您还可以从ApplicationController内部安装中间件,这意味着所有初始化程序和所有内容都已经执行,因此它可能在链中太远。