Reputation: 30766
I'm trying to add two extra config options to my application.rb so I can read them out in controllers.
# Extra
config.twitter.key = 'foo'
config.twitter.secret = 'bar'
I am trying to access them using three suggested methods:
self.config.twitter.key # Should be extended through ApplicationController Base
config.twitter.key # Inherited but with different syntax
CONFIG['twitter']['key'] #some massive magical array that apparently exists somewhere
They all give me different kinds of error when I pass them through the "debug" method, E.g:
debug self.config.twitter.key # undefined method `key' for nil:NilClass
So, whats going on?
Upvotes: 24
Views: 19352
Reputation: 2306
I believe you've got a slightly incorrect idea behind what your expectations for the config/application.rb is providing you. The ActiveRecord::Base and ActiveController::Base eigenclasses use the Rails::Application::Configuration class that is configured in config/application.rb. The attributes aren't available in classes that descend from either of the Base classes, nor their eigenclasses. This is why you are running into errors in ApplicationController.
There are generally two ways to make configuration initializations in a Rails app. The first way is to create a configuration module and then load values into it via initializer:
First, create a Twiter Config module:
#lib/twitter_config.rb
module TwitterConfig
def self.config
@@config ||= {}
end
def self.config=(hash)
@@config = hash
end
end
Create a YAML config file:
# config/twitter.yaml
development: &base
key: "foo"
secret: "bar"
test:
<<: *base
key: "foo2"
production:
<<: *base
secret: "barbar"
Alternatively, if you don't intend to add config/twitter.yaml to your SCM, you can just skip this and set the key and secret via environment variables. This would be the suggested solution for an application with a public SCM repository deploying on Heroku.
Then load and set the value via an initializer:
#config/initializers/01_twitter.rb
require 'twitter_config'
TwitterConfig.config = YAML.load_file("config/config.yml")[Rails.env].symbolize_keys
It's generally a best practice to number your initializer files as Rails will load them in order according to their filename. If you are initializing a datastore and that is critical for other steps, then it needs the lowest number. Alternatively, if you are using environment variables, this would be the init file:
#config/initializers/01_twitter.rb
require 'twitter_config'
TwitterConfig.config[:key] = ENV['twitter_config_key']
TwitterConfig.config[:secret] = ENV['twitter_config_secret']
Throughout the Rails application, you now have access to the config values with TwitterConfig.config[:key] & TwitterConfig.config[:secret]. You can include the module as well, just watch out for conflicts.
You can also just load the values as a global constant. It feels a bit ugly to me though:
#config/application.rb
TWITTER_CONFIG = YAML.load_file("config/twitter.yaml")[Rails.env]
Upvotes: 44
Reputation: 3130
I've tried this and seems to be working, you can use ::Rails.application.config.
For example I'm using it to get the correct time_zone set in the application like this:
Rails.application.config.time_zone
I found it thanks to the less-rails code: https://github.com/metaskills/less-rails/blob/master/lib/less/rails/helpers.rb
So you can declare this in your application.rb or in any enviroment file:
config.twitter_key = 'foo'
And then read it like so anywhere in your code:
Rails.application.config.twitter_key
Upvotes: 13
Reputation: 1326
A small update to the widely accepted answer here : Accessing config from application.rb in Controller (Rails 3)
The methods inside the module TwitterConfig should be class methods (or module methods if you prefer it that way). They can't be instance methods.
Sorry to put this in an answer, but I could not find a way to comment on that answer.
Upvotes: 0
Reputation: 47
Just put a file in config/initializers/
like app_config.rb
If you use ENV constant you can later on easily deploy to Heroku setting the values with the heroku config:add twitter_key=mypublickey
command.
Something like this:
## config/initializers/app_config.rb
unless Rails.env.production?
ENV['twitter_key'] = 'foo'
ENV['twitter_secret'] = 'bar'
end
You keep your production keys out of revision control and don't need to dribble with YAML-files.
Upvotes: -1
Reputation: 1438
You might want to consider using a yaml file approach.
In application.rb
CONFIG = YAML.load_file("config/config.yml")[Rails.env]
In config/config.yml
development: &base_config
twitter_key = "foo"
twitter_secret = "bar"
test:
<<: *base_config
twitter_key = "foo2"
production:
<<: *base_config
twitter_secret = "barbar"
Same usage as before with definable attributes on an environment level with overloading.
CONFIG['twitter_key']
Upvotes: 5