开发者

Passing variables to config/environments/demo.rb from the Rails app

开发者 https://www.devze.com 2023-04-10 01:16 出处:网络
I have been struggling with a problem for the past days in a Ruby on Rails App I\'m currently working on. I have different countries and for each country we use different Amazon S3 buckets. Amazon S3

I have been struggling with a problem for the past days in a Ruby on Rails App I'm currently working on. I have different countries and for each country we use different Amazon S3 buckets. Amazon S3 key credentials are stored as constants in config/environments/environment_name.rb(ex:demo.rb) There is no way for me to determine which country we are operating from the config file. I can determine which country we are operating from the controllers,models,views,etc but not from the config file. Is there a Ruby meta programming or some other kind of magic that I'm not aware of so that I want to say if we are working on UK as a country in the app, use UK's bucket credentials or Germany as a country, use Germany's bucket credentials? I can't think of a way to pass parameters to environment files from开发者_如何学运维 the app itself. Thank you very much in advance for all your helps.


Rather than actually pass the configuration details to whichever S3 client you're using at launch, you should probably select the relevant credentials for each request. Your config file can define them all in a hash like so:

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

Then you can select the credentials on request like so (in maybe your AppController):

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

Make sense?


Write a little middleware if you want to keep the knowledge of the per-country configuration out of the main application.

A middleware is extremely simple. A do-nothing middleware looks like this:

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

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

Rack powers applications through chaining a series of middlewares together... each one is given a reference to @app, which is the next link in the chain, and it must invoke #call on that application. The one at the end of the chain runs the app.

So in your case, you can do some additional configuration in here.

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

There are several ways to use the middleware, but since it depends on access to the Rails environment, you'll want to do it from inside Rails. Put it in your application.rb:

config.middleware.use PerCountryConfiguration

If you want to pass additional arguments to the constructor of your middleware, just list them after the class name:

config.middleware.use PerCountryConfiguration, :some_argument

You can also mount the middleware from inside of ApplicationController, which means all of the initializers and everything will have already been executed, so it may be too far along the chain.

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号