Assigning Environment Variables in Ruby on Rails - ruby-on-rails

I have a program that makes calls to an internal web API. However when we're doing development work on the sites we don't want the program to call our production web API but the staging version of the Web API. What's the best way to do this in rails?
I feel I should be assigning some sort of variable in development.rb and one in production.rb
Thanks

Yes, just add a variable to development.rb and production.rb like:
OUR_API_URL = "http://somepath"
Then you can use OUR_API_URL in your code.

Related

Rails adding translations to a running rails environment

Is there a way to manually inject a translation through the Rails console ?
Suppose I am working on a dev environment, and I want to test some code in a production console (eg to test some statistics on real data).Problem is, the code I want to test relies on new translations that didn't exist (or were changed) in the production environment.
So my code returns a lot of translation_missing
Can I inject the missing translations ? Via a hash or a YML file ?
I18n.load_translations(hash_or_file)
Usually Application instances that serve http requests (for example running under Unicorn/Puma) are not available via Rails console. When someone login to production server and type $RAILS_ENV=production rails c it starts another application process. Translations dictionary is a kind of in-memory cache and usually it is not possible to change that cache for/from another process (in general). You can reload translations only for application instance that started by Rails console, but not for running server.
Only one way to hot reload translations is adding kind of a hook into source code of application to re-read YAML file, but it seems better just restart application server.
UPDATE: For testing purposes I18n cache could be modified like:
I18n.backend.send(:translations)[:en][:date][:formats][:default] = "%Y-%Z"

Use Ruby on Rails environment config based on URL/Machine Name

I have a RoR3 app with multiple environment configs, development.rb, test.rb and production.rb.
Is there a way I can instruct the application to used a specific config based on a value in the URL or machine name??
For instance if the machine name contains "dev", then use development.rb.
Edit
If that is not possible, is there a way I can access the request URL from the application.rb or environment.rb files maybe. If so, I could probably use a regex on the URL to determine and set the environment settings dynamically within if blocks.
In the end, we'll end up having many more than just 3 environments, all with certain differences. So I need a very flexible way to set the config.
Probably not. By the time the rails app is running (and can look at the machine name) it's already picked an environment. Unless you hack the boot script...
It'd be much easier to just put the environment into the startup-command-line for each machine.

Adding urls api keys in environment variable in ruby

I have a url that I am using in one of the controllers. Is there a better place to put this url? The url uses an API key and I was wondering if there is a better place to add this url and/or api key such that its not added in the controller class code and ergo more editable? If i add it as an environment variable or anything else how do i access it from my controller class? thank you. ITS A RUBY AND RAILS PROJECT
Using environment variables might be a good idea if you want to keep things like API keys and passwords out of your source code. Accessing them from within your code is done with the ENV object:
my_api_key = ENV['MY_API_KEY']
To use this technique, you need to set up the variables in your environment before launching your app, and how you do this depends on your local setup, and will likely also vary between development and production.
In development, you can simply set the environment vars in your shell, e.g. with bash:
$ export MY_API_KEY=foobar123abc
$ rails s
Now rails will start and have access to this environment variable. You can also set variables for just a single command:
$ MY_API_KEY=foobar123abc rails s
Depending on what the sevice/api is, you could set some of them to default development/test values in config/environments/development.rb (or test.rb):
ENV['MY_API_KEY'] = 'non_secret_api_key_that_can_be_shared_around'
Setting up environment variables in production will depend on how you're deploying your app. Phusion have an article on using environment variables in Passenger if your using that. There's also a useful article on using environment variables with Heroku which is worth a read even if you're not using them for deployment.
You can add it to application.rb file as
config.service {
:api_key => 'api_key'
}
Or better yet, add it to development.rb and production.rb files so that you can test it better.
You can access this api_key from controller like
Rails.application.config.service[:api_key]

How can I manage a different setup for my Ruby on Rails application dependent on production or development?

I am trying to deploy my first rails app and struggling a bit. My plan is to initially host it on a heroku free account to get a feel for live deployments and do some production testing. Eventually I might move it to a VPS.
I use git and do not use Capistrano at the moment.
Heroku primarily uses git, which is fine, but git manages the entire project state not files. So I have issues managing configuration files that are different from production to development, for example captcha keys in the environment.rb or goolge js api keys.
So what I did was to..
1 - Take the environment specific configuration out of the enviornment.rb and put it in the development.rb and production.rb. Created a branch called dev where I do my development and then merge it with master and push master to the production heroku remote.
This all works ok, but wondering if there is a better way to do it.
The other massive problem is I might have to use different gems in dev and in herouku. For example, I use ThinkingSphinix for search in dev, but Heroku I have to use acts_as_solr, which means my "Article.search call in the controller, will have to be Article.find_by_solr in production. This can become messy very fast.
What's the best way to deal with this kind of situation?
Thanks
For non-sensitive keys such as Google's JS API key etc., I found this RailsCasts episode very helpful.
Just created a config file under config/ and store your development settings in there.
# /config/google.yml
development:
google:
js:
key: 123456
test:
google:
js:
key: 345678
production:
google:
js:
key: 567890
Then create an initializer inside config/initializers/ that will parse the yaml and create an object which can be used without worrying about the current environment.
# /config/initializers/google.rb
GOOGLE_CONFIG = YAML.load_file("#{RAILS_ROOT}/config/google.yml")[RAILS_ENV]
The environment variable RAILS_ENV refers to the current environment, so on application startup it picks up the current type, and you can refer to the settings in your code through GOOGLE_CONFIG:
<script type="text/javascript" src="http://www.google.com/jsapi?key=<%= GOOGLE_CONFIG['js']['key'] %>"></script>
For the latter issue, where code itself differs from environment to environment, I believe Capistrano would be a better solution.
For values that you want to keep different between environments, Heroku offers config vars.
As for using one indexing program in production and another in development, that's a bad idea, and will make things way messier than they need to be. Either start using Solr locally, or set up a Thinking Sphinx instance in EC2 yourself, and have your dynos connect to it.
I would suggest that it is very unwise to have different code in development and production.
Your development, test and production environments should be as similar as possible.
In fact, I would go so far as to say the entire point of the different environments is to simply provide an easy system for allowing minor configuration changes between setups. Different databases, different API parameters, different aching options, but the core system MUST be the same.
The the issue you will face is doubling your development effort. You still have to write the code. So in the search example you provide above, you will have to develop and test twice - once for the Solr production system and once for you local Sphinx, then you need to be able to switch and test between the two approaches in all of your environments to ensure test coverage and functionality.

How to use a Rails environment variable in Capistrano deploy script?

If I have a constant in my Rails environment.rb, for example...
SOME_CONSTANT = 3
Is it possible to access this in my capistrano deploy.rb somehow? It seems simple but I can't figure out how.
This ended up working:
created a file config/initializers/my_constant.rb
put my constant in there (rails automatically loads files there so I can use the constant in my app)
then in deploy.rb added load 'config/initializers/my_constant' so it could be used there as well.
You should access it via the ENV[] hash (this is a Ruby thing), here is an example using the TERM environmental variable.
puts "Your Terminal is #{ENV['TERM']}"
If you need a ruby constant, from your rails environment, you should load it:
require 'config/environment'
Beware that this will load your whole application environment, you should think to use something like AppConfig, or SimpleConfig (insert other tool here) to store configurations, then you need only load the tool, which processes your config files.
Why not define these constants in a file in lib/ and then require the file in both your Rails app and your Capfile?
As the value is not only used by the rails app, I would probably store such configuration information in a language agnostic format (yaml, json, ini, xml) which can be easily parsed by different tools without fear of possible side effects.

Resources