How do I pass in my API key as an environment variable - ruby-on-rails

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.

Related

Rails Postgres config host mistaken as database name

have been pulling my hair due this issue :
When I run my rails application on my mac it seems the host is mistaken as database name and it only happens on development environment.
This is my database.yml :
default: &default
adapter: postgresql
encoding: unicode
pool: 5
username: <%= ENV['DATABASE_USERNAME'] || 'admin' %>
password: <%= ENV['DATABASE_PASSWORD'] || 'password'%>
host: <%= ENV['DATABASE_URL'] || 'localhost'%>
development:
<<: *default
database: cid_dev
test:
<<: *default
database: cid_test
production:
<<: *default
database: cid_api
Then when I run :
$ bundle exec rake db:create
It returns me this :
Database 'localhost' already exists
anyone has any idea what happen in my local environment ?
FYI, I tried rbenv and rvm both has same issue.
Thank you.
I found the answer myself.
Rails using DATABASE_URL environment variable as a place to put connection string. So when I put database host inside env variable DATABASE_URL it will use it as default
https://github.com/rails/rails/blob/fb764ba63e53b728873075a0d207b993409798a2/railties/lib/rails/application/configuration.rb#L88-L102
So to fix it what I need is rename DATABASE_URL to DATABASE_HOST which is the correct one anyway. Thank you

Figaro store passwords rails

I have install figaro gem.
My application.yml file:
user: 'm#am.com'
pwd: = 'password123'
Also I have in secrets.yml this:
development:
secret_key_base: d2c6dc60d0c86d32c71aa2ec2ae1fff32f338187ceaa12f0d6a294f368760ead01bc1c57115d48b80ab4042b45ca5aceadea1e888f34b5a14ab548eb07e1ad9c
test:
secret_key_base: f4c0aad565527a57110ccba77def71e2dd1b65799b94d4d24f9b34a8bc42fd01dbc64349c5555dca46b4d5d2ba85f890c718c1de0d20237704c788e4db928c66
# Do not keep production secrets in the repository,
# instead read values from the environment.
production:
secret_token: ENV["secret_token"]
secret_key_base: ENV["secret_key_base"]
user: ENV["user"]
pwd: ENV["pwd"]
key: ENV["key"]
And I get user login like this:
Rails.application.secrets[:user]
Which gives me exactly this value:
"ENV[\"user\"]"
So what do I do?
seems like I should use
ENV["key"]
instead of Rails.application.secrets[:user]

Is there a way to specify a secret for all environments in secrets.yml from rails 4.1?

Like the question states, is there a way to make a secret known to all 3 environments without copy and pasting like this?
secrets.yml
development:
secret_key_base: ...
my_global_secret: foo
test:
secret_key_base: ...
my_global_secret: foo
production:
secret_key_base: ...
my_global_secret: foo
You can define and share a common key using &label and <<: *label
common: &common
secret_key_base: ...
my_global_secret: foo
development:
<<: *common
something_specific_to_development: ...
test:
<<: *common
something_specific_to_test: ...
production:
<<: *common
something_specific_to_production: ...
Update: For Rails 5.1+
Rails 5.1 adds the shared key which is automatically applied to all environments:
shared: # Everything nested under this key is automatically shared
secret_key_base: ...
my_global_secret: "foo"
development:
my_global_secret: "override value for dev"
test:
...
Using common: &common didn't work for me with Rails 5.1 - shared: did though.

Rails: constant not initializing

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.

Best way to create custom config options for my Rails app?

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

Resources