Storing configuration variable in ruby on rails - ruby-on-rails

I'm storing configuration variables for different environments in the production.rb and development.rb
production.rb
ENV['my_variable'] = 'val1'
development.rb
ENV['my_variable'] = 'val2'
Maybe exists another way to store variables for different environments. What is the best way?

I've been pointing people towards the settingsgem lately. Settings Gem

Related

Rails: How to change the logger filename?

I'd like to change the logger filename. The default, say, on production, is production.log.
I'd like it be customized, for example, to production.mymachine.log.
How can I do this? I can't find any obvious way.
You can change this application wide in config/application.rb or for each environment in their dedicated files in config/environments
# e.g. in config/environments/development.rb
config.logger = Logger.new(Rails.root.join('log', 'development.my_machine.log'))

Rails 5 not loading encrypted secrets in production.rb

I have a project configured to use Rails encrypted secrets. Everything works fine until I try to access a secret within the production.rb environment file.
I found that if I try to access something like Rails.application.secrets.smtp_user_name within the configure block it wipes out all of the encrypted secrets (I'm only left with things in secrets.yml ... which I'm not using). Example:
Loading production environment (Rails 5.1.2)
irb(main):001:0> Rails.application.secrets
=> {:secret_key_base=>nil, :secret_token=>nil}
If I remove the attempt to access the secrets it works correctly:
irb(main):001:0> Rails.application.secrets
=> {:secret_key_base=>"...", :smtp_user_name=>"...", :smtp_password=>"...", :secret_token=>nil}
I'm currently working around it by using two configure blocks in production.rb as follows:
# This is hacky, it needs to come before the second configure block where
# the encrypted secrets are used.
Rails.application.configure do
config.read_encrypted_secrets = true
end
Rails.application.configure do
... stuff that uses Rails.application.secrets, like ActionMailer
end
Anybody else faced this and possibly have a more correct way to work around it?
It makes sense why this is happening (Rails doesn't know to load the encrypted secrets because we haven't told it to you), but I'm thinking there must be a better way to deal with it.
Update
This nailed me again 9 months later. To be clear, if you reference Rails.application.secrets BEFORE calling config.read_encrypted_secrets = true you will cache empty secrets and not be able to access any of the values in secrets.yml.enc!
In my case I had tried to configure Paperclip S3 credentials in application.rb while my config.read_encrypted_secrets = true was set in production.rb. Result was devise.rb blowing up trying to read a secret for the key base, all because in application.rb I had effectively cached nil secrets.
here is bug report related to your issue:
https://github.com/rails/rails/issues/30362#issuecomment-326821656
In general even if you have all things set up properly you need check also order how your application loads secrets. If your application ask first for Rails.application.secrets and then set proper flag... Rails.application.secrets will cache version without secrets... and Secrets from secret.yml.enc will not be merge.

Handling properties/configurations in Rails

I want to be able to move hard-coded configuration outside of my .rb files.
I don't want to have stuff like this:
config.action_mailer.default_url_options = {
:host => 'www.mydomain.com',
}
I need it to be easy to change between different machines.
What will be the best path to achieve that?
Thanks
Usually configuration stuff is intended to stay inside .rb files -- that's the best path to achieve different configurations in different environments.
So if you have a production environment and a beta environment, in beta.rb you'd have:
config.action_mailer.default_url_options = {
:host => 'beta.mydomain.com',
}
And in production.rb you'd have:
config.action_mailer.default_url_options = {
:host => 'www.mydomain.com',
}
If you're trying to store your configuration settings elsewhere, you're probably trying to vary the settings because your deployment environment isn't static (like EC2, where you could be bringing up and down machines constantly with different IPs). In that case, I'd recommend investigating a tool like rubber or chef that provide programmatic ways to transform configuration files.

Rails & Devise: how to configure mail with domain name automatically?

I need some advice on configuring mail in production Ruby-on-Rails sites.
I deploy my Rails app on EngineYard. I have a couple of sites, like demo.mydomain.com or staging.mydomain.com - how can I configure Devise so that at deploy time I can make sure confirmation mails come from demo.mydomain.com or staging.mydomain.com automatically? ie, I want the same GitHub codebase, and want to fill the configuration in dynamically.
Currently in config/environments/production.rb I have the line:
config.action_mailer.default_url_options = { :host => 'demo.mydomain.com' }
But that's incorrect when the same code is deployed to staging.mydomain.com as they both run in RAILS_ENV=production
Any ideas?
Thanks,
Dave
Update: For now, to be practical, I've added specific environments to hardcode the mailer domain. So now demo.mydomain.com runs on environments/demo.rb, and www.mydomain.com runs on environments/productions.rb. What I don't like about this is the duplication between the files, it's not clear to me how to DRY them up as I have with, eg, database.yml
in your devise configuration, usually config/initializers/devise.rb you can configure the mail-sender for devise. this configuration takes a proc, so that it's possible to evaluate something at runtime.
Devise.setup do |config|
config.mailer_sender = Proc.new { your_magic_here }
end
Ideally staging & production servers should run on different rails environment. Still if you wanted to have production env running on both staging & production servers with different action mailer urls then it should be done at deployment level. You can always write environment file while deployment.
First of all, I think you should separate the environments of your application. Check this guide to learn how you can do it.
Then, try something like this in your devise configuration:
Devise.setup do |config|
if Rails.env.production?
config.mailer_sender = "no-reply#domain.com"
elsif Rails.env.staging?
config.mailer_sender = "no-reply#staging.domain.com"
else
config.mailer_sender = "no-reply#domain.com"
end
...
Check this guide to understand more about Proc object.

What is the best way to store app specific configuration in rails?

I need to store app specific configuration in rails. But it has to be:
reachable in any file (model, view, helpers and controllers
environment specified (or not), that means each environment can overwrite the configs specified in environment.rb
I've tried to use environment.rb and put something like
USE_USER_APP = true
that worked to me but when trying to overwrite it in a specific environment it wont work because production.rb, for instance, seems to be inside the Rails:Initializer.run block.
So, anyone?
Look at Configatron: http://github.com/markbates/configatron/tree/master
I have yet to use it, but he's actively developing it now, and looks quite nice.
I was helping a friend set up the solution mentioned by Ricardo yesterday. We hacked it a bit by loading the YAML file with something similar to this (going from memory here):
require 'ostruct'
require 'yaml'
require 'erb'
#config = OpenStruct.new(YAML.load_file("#{RAILS_ROOT}/config/config.yml"))
config = OpenStruct.new(YAML.load(ERB.new(File.read("#{RAILS_ROOT}/config/config.yml")).result))
env_config = config.send(RAILS_ENV)
config.common.update(env_config) unless env_config.nil?
::AppConfig = OpenStruct.new(config.common)
This allowed him to embed Ruby code in the config, like in Rhtml:
development:
path_to_something: <%= RAILS_ROOT %>/config/something.yml
The most basic thing to do is to set a class variable from your environment.rb. I've done this for Google Analytics. Essentially I want a different key depending on which environment I'm in so development or staging don't skew the metrics.
This is how I did it.
In lib/analytics/google_analytics.rb:
module Analytics
class GoogleAnalytics
##account_id = nil
cattr_accessor :account_id
end
end
And then in environment.rb or in environments/production.rb or any of the other environment files:
Analytics::GoogleAnalytics.account_id = "xxxxxxxxx"
Then anywhere you ned to reference, say the default layout with the Google Analytics JavaScript, it you just call Analytics::GoogleAnalytics.account_id.
I found a good way here
Use environment variables. Heroku uses this. Remember that if you keep configuration in the codebase, anyone with access to the code has access to any secret configuration (aws api keys, gateway api keys, etc).
daemontool's envdir is a good tool for setting configuration, I'm pretty sure that's what Heroku uses to give application their environment variables.
I have used Rails Settings Cached.
It is very simple to use, keeps your configuration values cached and allows you to change them dynamically.

Resources