I need to create one config option for my Rails application. It can be the same for all environments. I found that if I set it in environment.rb, it's available in my views, which is exactly what I want...
environment.rb
AUDIOCAST_URI_FORMAT = http://blablalba/blabbitybla/yadda
Works great.
However, I'm a little uneasy. Is this a good way to do it? Is there a way that's more hip?
For general application configuration that doesn't need to be stored in a database table, I like to create a config.yml file within the config directory. For your example, it might look like this:
defaults: &defaults
audiocast_uri_format: http://blablalba/blabbitybla/yadda
development:
<<: *defaults
test:
<<: *defaults
production:
<<: *defaults
This configuration file gets loaded from a custom initializer in config/initializers:
# Rails 2
APP_CONFIG = YAML.load_file("#{RAILS_ROOT}/config/config.yml")[RAILS_ENV]
# Rails 3+
APP_CONFIG = YAML.load_file(Rails.root.join('config/config.yml'))[Rails.env]
If you're using Rails 3, ensure you don't accidentally add a leading slash to your relative config path.
You can then retrieve the value using:
uri_format = APP_CONFIG['audiocast_uri_format']
See this Railscast for full details.
Rails 3 version of initialiser code is as follows (RAILS_ROOT & RAILS_ENV are deprecated)
APP_CONFIG = YAML.load_file(Rails.root.join('config', 'config.yml'))[Rails.env]
Also, Ruby 1.9.3 uses Psych which makes merge keys case sensitive so you'll need to change your config file to take that into account, e.g.
defaults: &DEFAULTS
audiocast_uri_format: http://blablalba/blabbitybla/yadda
development:
<<: *DEFAULTS
test:
<<: *DEFAULTS
production:
<<: *DEFAULTS
Rails >= 4.2
Just create a YAML file into config/ directory, for example: config/neo4j.yml.
Content of neo4j.yml can be somthing like below(For simplicity, I used default for all environments):
default: &default
host: localhost
port: 7474
username: neo4j
password: root
development:
<<: *default
test:
<<: *default
production:
<<: *default
in config/application.rb:
module MyApp
class Application < Rails::Application
config.neo4j = config_for(:neo4j)
end
end
Now, your custom config is accessible like below:
Rails.configuration.neo4j['host'] #=>localhost
Rails.configuration.neo4j['port'] #=>7474
More info
Rails official API document describes config_for method as:
Convenience for loading config/foo.yml for the current Rails env.
If you do not want to use a yaml file
As Rails official guide says:
You can configure your own code through the Rails configuration object with custom configuration under the config.x property.
Example
config.x.payment_processing.schedule = :daily
config.x.payment_processing.retries = 3
config.x.super_debugger = true
These configuration points are then available through the configuration object:
Rails.configuration.x.payment_processing.schedule # => :daily
Rails.configuration.x.payment_processing.retries # => 3
Rails.configuration.x.super_debugger # => true
Rails.configuration.x.super_debugger.not_set # => nil
Official Reference for config_for method |
Official Rails Guide
Step 1: Create config/initializers/appconfig.rb
require 'ostruct'
require 'yaml'
all_config = YAML.load_file("#{Rails.root}/config/config.yml") || {}
env_config = all_config[Rails.env] || {}
AppConfig = OpenStruct.new(env_config)
Step 2: Create config/config.yml
common: &common
facebook:
key: 'asdjhasxas'
secret : 'xyz'
twitter:
key: 'asdjhasxas'
secret : 'abx'
development:
<<: *common
test:
<<: *common
production:
<<: *common
Step 3: Get constants anywhere in the code
facebook_key = AppConfig.facebook['key']
twitter_key = AppConfig.twitter['key']
I just wanted to update this for the latest cool stuff in Rails 4.2 and 5, you can now do this inside any of your config/**/*.rb files:
config.x.whatever = 42
(and that's a literal x in there, ie. the config.x. literally must be that, and then you can add whatever you want after the x)
...and this will be available in your app as:
Rails.configuration.x.whatever
See more here: http://guides.rubyonrails.org/configuring.html#custom-configuration
Just some extra info on this topic:
APP_CONFIG = YAML.load_file(Rails.root.join('config', 'config.yml'))[Rails.env].with_indifferent_access
".with_indifferent_access" allows you to access the values in the hash using a string key or with an equivalent symbol key.
eg.
APP_CONFIG['audiocast_uri_format'] => 'http://blablalba/blabbitybla/yadda'
APP_CONFIG[:audiocast_uri_format] => 'http://blablalba/blabbitybla/yadda'
Purely a convenience thing, but I prefer to have my keys represented as symbols.
I use something similar to John for Rails 3.0/3.1, but I have erb parse the file first:
APP_CONFIG = YAML.load(ERB.new(File.new(File.expand_path('../config.yml', __FILE__)).read).result)[Rails.env]
This allows me to use ERB in my config if I need to, like reading heroku's redistogo url:
production:
<<: *default
redis: <%= ENV['REDISTOGO_URL'] %>
Rails 4
To create a custom configuration yaml and load it (and make available to your app) similar to how database_configuration.
Create your *.yml, in my case I needed a redis configuration file.
config/redis.yml
default: &default
host: localhost
port: 6379
development:
<<: *default
test:
<<: *default
production:
<<: *default
host: <%= ENV['ELASTICACHE_HOST'] %>
port: <%= ENV['ELASTICACHE_PORT'] %>
Then load the configuration
config/application.rb
module MyApp
class Application < Rails::Application
## http://guides.rubyonrails.org/configuring.html#initialization-events
config.before_initialize do
Rails.configuration.redis_configuration = YAML.load_file("#{Rails.root}/config/redis.yml")
end
end
end
Access the values:
Rails.configuration.redis_configuration[Rails.env] similar to how you can have access to your database.yml by Rails.configuration.database_configuration[Rails.env]
Building on Omer Aslam's elegant solution, I decided to convert the keys into symbols. The only change is:
all_config = YAML.load_file("#{Rails.root}/config/config.yml").with_indifferent_access || {}
This allows you to then reference values by symbols as keys, e.g.
AppConfig[:twitter][:key]
This seems neater to my eyes.
(Posted as an answer as my reputation isn't high enough to comment on Omer's reply)
I like simpleconfig. It allows you to have per environment configuration.
see my response to Where is the best place to store application parameters : database, file, code...?
A variation to what you had in that it's a simple reference to another file. It sees that environment.rb isn't constantly updated and doesn't have a heap of app specific stuff in it.
Though not a specific answer to your question of 'is it the Rails way?', perhaps there'll be some discussion there about that.
I prefer accessing settings through the global application stack. I avoid excess global variables in local scope.
config/initializers/myconfig.rb
MyAppName::Application.define_singleton_method("myconfig") {YAML.load_file("#{Rails.root}/config/myconfig.yml") || {}}
And access it with.
MyAppName::Application.myconfig["yamlstuff"]
My way to load Settings before Rails initialize
Allows you to use settings in Rails initialization and configure settings per environment
# config/application.rb
Bundler.require(*Rails.groups)
mode = ENV['RAILS_ENV'] || 'development'
file = File.dirname(__FILE__).concat('/settings.yml')
Settings = YAML.load_file(file).fetch(mode)
Settings.define_singleton_method(:method_missing) {|name| self.fetch(name.to_s, nil)}
You could get settings in two ways:
Settings['email'] or Settings.email
My best way to custom config, with raise message when setting.yml is missing.
gets loaded from a custom initializer in config/initializers/custom_config.rb
setting_config = File.join(Rails.root,'config','setting.yml')
raise "#{setting_config} is missing!" unless File.exists? setting_config
config = YAML.load_file(setting_config)[Rails.env].symbolize_keys
#APP_ID = config[:app_id]
#APP_SECRET = config[:app_secret]
Create a YAML in config/setting.yml
development:
app_id: 433387212345678
app_secret: f43df96fc4f65904083b679412345678
test:
app_id: 148166412121212
app_secret: 7409bda8139554d11173a32222121212
production:
app_id: 148166412121212
app_secret: 7409bda8139554d11173a32222121212
Related
I am using themoviedb-api ruby gem in rails 4 and I would like to keep my API key out of git so I though of passing it in as an environment variable. What is the correct syntax?
In my .env I have
TMDB_API_KEY=ee27f0e6fxxxxxxxxxxxxxxxx
In my initializers/tmdb.rb I have
Tmdb::Api.key("KEY_HERE")
I have tried a few different ideas but nothing has worked. Like ENV['TMDB_API_KEY'] for example.
Thanks in advance.
By default, you can't just stick things in .env and have them work. You'll need to use a gem like dotenv. https://github.com/bkeepers/dotenv
You can then access it using ENV['VAR_NAME']
in application.rb:
config.before_configuration do
env_file = Rails.root.join("config", "environment_variables.yml").to_s
if File.exists?(env_file)
YAML.load_file(env_file)[Rails.env].each do |key, value|
ENV[key.to_s] = value
end
end
end
in /config/environment_variables.yml:
default: &default
key: "development_key"
development:
<<: *default
test:
<<: *default
production:
<<: *default
key: "production_key"
anywhere in your code:
ENV["key"] should point to the right value for the current environment.
Suppose you have a similar YAML configuration file:
defaults: &defaults
# registration form
birth_date: true
address: true
zip: true
city: true
state: true
# other stuff
send_email_notification_to_users: true
production:
<<: *defaults
development:
<<: *defaults
test:
<<: *defaults
which is loaded in a similar way to how it is explained in Railcast #85:
http://railscasts.com/episodes/85-yaml-configuration-file
Suppose you need to test how the application performs with different settings, how would you do that?
With Django it is possible to change the settings temporarily during unit tests:
https://docs.djangoproject.com/en/dev/topics/testing/overview/#overriding-settings
Is it possible to do something similar with Rails?
In case you implemented it exactly like it is explained in Railscast #85, simply assign the new value like so:
APP_CONFIG['perform_authentication'] = false
# or
APP_CONFIG['my_fancy_key'] = 'my fancy value'
Keep in mind that the value will not be changed back automatically after your test case finished, so it will remain valid for all subsequent test cases.
change the configurations dynamically, using maybe before and after blocks:
before(:all) do
#old_config = APP_CONFIG
APP_CONFIG = YAML.load_file("#{RAILS_ROOT}/config/config.yml")["production"]
end
after(:all) do
APP_CONFIG = #old_config
end
I am trying to use different stripe keys (a credit card payment processing system) depending on whether I'm in test/development or production/ Based on suggestions I've seen on StackOverflow, I did the following:
In my /config/initalizers/stripe.rb file, I have the following:
STRIPE_CONFIG = begin
config = YAML.load(File.open(Rails.root.join('config', 'stripe.yml')))
config = config[Rails.env] || {}
config.to_options
end
and in my /config/stripe.yml file, I have the following:
default: &default
Stripe.api_key: "testapikeycode"
STRIPE_PUBLIC_KEY: "testpublickeycode"
development:
<<: *default
test:
<<: *default
production:
Stripe.api_key: "productionapikeycode"
STRIPE_PUBLIC_KEY: "productionpublickeycode"
However, when I go into the console (rails console), and I type
puts STRIPE_PUBLIC_KEY
I get the following error message:
NameError: uninitialized constant STRIPE_PUBLIC_KEY
Any ideas?
Alternate method
Only use stripe.rb, and have the following in it:
if Rails.env == 'production'
Stripe.api_key: "productionapikeycode"
STRIPE_PUBLIC_KEY: "productionpublickeycode"
else
Stripe.api_key: "tesapikeycode"
STRIPE_PUBLIC_KEY: "testpublickeycode"
end
STRIPE_PUBLIC_KEY is a key in your yaml config file, you never actually initialize it as a constant. If you type p STRIPE_CONFIG['STRIPE_PUBLIC_KEY'] instead you should get the result you want.
Aside I think YAML.load should be YAML.load_file.
In my app, I have many constants, so I made a constants file named det_constants.yml for these constants.
/config/det_constants.yml
DEFAULTS: &DEFAULTS
company_type: { "Private" : 1,
"Public" : 2 }
development:
<<: *DEFAULTS
test:
<<: *DEFAULTS
production:
<<: *DEFAULTS
I have a constants.rb file in lib folder, which loads this constant file.
/lib/constants.rb
module Constants
# Allows accessing config variables from det_constants.yml like so:
# Constants[:abc] => xyz
def self.[](key)
unless #config
raw_config = File.read(Rails.root.to_s + "/config/det_constants.yml")
#config = YAML.load(raw_config)[Rails.env].symbolize_keys
end
#config[key]
end
def self.[]=(key, value)
#config[key.to_sym] = value
end
end
In my view file, when I do
<%= Constants[:company_type] %>
it throws an error
NameError in Vendors#index
uninitialized constant ActionView::CompiledTemplates::Constants
at line
<%= Constants[:company_type] %>
However, If i do the same thing in console, it runs properly,
ruby-1.9.2-head > Constants[:company_type]
=> {"Private"=>1, "Public"=>2}
I don't know where is the problem. if there is a new and better way to do this in Rails 3, please let me know.
Ruby version: ruby 1.9.2p110 (2010-12-20 revision 30269) [i686-linux]
Rails version: Rails 3.0.3
I imagine you need:
<% require 'constants' %>
Also, you will need to restart the server following changes in lib/; it doesn't catch them automatically even in development mode.
What about other solutions, I recommend you watch the railscast called YAML Configuration File. There are also some gems such as Settingslogic to help you with that.
Greetings
I am trying to get Mongoid to work with my Rails app and I am getting
an error: "Mongoid::Errors::InvalidDatabase in 'Shipment bol should be
unique' Database should be a Mongo::DB, not NilClass"
I have created the mongoid.yml file in my config directory and have mongodb running as a daemon. The config file is like so:
defaults: &defaults
host: localhost
development:
<<: *defaults
database: ship-it-development
test:
<<: *defaults
database: ship-it-test
production:
<<: *defaults
host: <%= ENV['MONGOID_HOST'] %>
port: <%= ENV['MONGOID_PORT'] %>
database: <%= ENV['MONGOID_DATABASE'] %>
All of my specs fail with the above error. I am using rails 2.3.8.
Anyone have ideas?
Like explain on question : How can i generate mongoid.yml config in Rail 2.3.5?
The mongoid.yml doesn't works with Rails 2.3.x. It's load automatic only with Rails 3.
You need add an initializer with loading your file and use it to define your database.
By example you can add that in an initializer.
mongoid_conf = YAML::load_file(Rails.root.join('config/mongoid.yml'))[Rails.env]
Mongoid.configure do |config|
config.master = Mongo::Connection.new(mongoid_conf['host'],
mongoid_conf['port']).db(mongoid_conf['database'])
end
Also if your writing your own non rails script and you initialize your models first then you will get this error.
You need to configure the database before initializing the model.
I hit this when writing a gem that used mongoid internally
Test cases hit it as well so put the Mongoid.configure section in your test/helper.rb