How can I load multiple YAML files in rails application.rb - ruby-on-rails

I have many yaml files in config/ And I want to load all yaml files.
EX: I have two .yml files name is: application.yml and linkedin.yml. I want to load both files with application.rb.
To achieve this goal I Have written code in application.rb:
ENV.update YAML.load_file('config/application.yml')[Rails.env] rescue {}
ENV.update YAML.load_file('config/linkedin.yml')[Rails.env] rescue {}
But this is not appropriate way, Please suggest me how can I load all yaml files access with ENV variable that.

Assuming that your YAML files are placed in the config folder, in your application.rb you can do this right under the requires (before the module definition)
APP_YAML = YAML::load_file(File.join(File.dirname(File.expand_path(__FILE__)), 'application.yml'))
LINKED_IN = YAML::load_file(File.join(File.dirname(File.expand_path(__FILE__)), 'linked_in.yml'))
This way, you can then access the contents of the file in a constant that is available everywhere in the app ie. LINKED_IN["secret"]
This is a great way to handle constants that you don't want to check in to source control, but actually I've found that using Figaro is the best way to handle constants. Essentially, Figaro will autogenerate/load an application.yml and all you have to do is put your constants in there.
After this, you can access with ENV["LINKED_IN_SECRET"] - as a plus, this emulates how Heroku would do it with their config:set variable system so you don't have to worry about environment changes :)

Related

Rails 4.2 constants - where to put them: application.yml vs custom config file.rb

I have some constants I am using throughout my app.
I'd say there are three types:
some are really passwords to external stuff like sendgrid login/password
some are internal "secret codes" like devise secret key
some are just what I'd call global constants that is to say there are constants that we use a lot throughout the app and don't want anybody to easily change this. They nearly never change. Some examples: the ID of our facebook page, or the number of deals "per page" we define in our infinite scrolling on the homepage (critical for UX), or the url of our brand-validated logo on aws cdn(present in many view files html.erb and assets javascript .js files). One aspect I also have in mind when asking my question, is that even if they seem less critical than a devise key, for those constants, I would like to gather, to make sure very few people and only authorized developers can change those critical data.
Here's what we do today:
For 1 and 2: I put the constants on config/application.yml
And for 3 : I put the constants on a custom .rb config file as described by official Rails guide (guides.rubyonrails.org/v4.2/configuring.html#custom-configuration)
For example: on /config/initializers/app_custom.rb
Rails.application.configure do
config.x.infite_scrollhp_feed_per_page_deals = 30
end
then it is called in a controller this way:
nb_per_page = Rails.configuration.x.infite_scrollhp_feed_per_page_deals
But each time I am unsure if I should put global constants inside config/application.yml or in my custom config .rb file?
What is the recommended "Rails -way"? How to decide where to put them ? Is there a generally accepted "good-sense"/"proven to be efficient/well-structuring" practice/rule ?
Also is there a different in performance that is to say are application.yml "injected" faster into view (.html) and assets(.js) files when user load a page than if they are defined on my custom config file ?
I would advise using config/secrets.yml for sensitive data (1 and 2):
development:
some_password: ...
test:
some_password: ...
production:
some_password: <%= ENV["SOME_PASSWORD"] %>
This way you can put different settings for different environments (for development, test and production).
And I would highly recommend keeping the production sensitive data in ENV variables.
When it goes for non sensitive data (3) I would put in config/environments/*.rb files when different settings are needed for different environments.
If that's not the case and the setting is the same for all environments, I would put it into application.rb, application.yml or in a custom file in initializers/* or even as class constants.

Storing some application settings in Rails app

There is the following task: My app has got one variable with name 'delivery_time'; this variable can be changed through admin panel. I think it's not a good way to store it in some database table. How can I store it in configs or anything else? May be I should store it in db yet?
You can easily store settings in the config file like this:
Create config.yml and store your settings
delivery_time: '...'
Add this config to initializers/load_config.rb
require 'ostruct'
require 'yaml'
app_config = YAML.load_file(File.join(::Rails.root, 'config', 'config.yml'))[Rails.env]
::AppConfig = OpenStruct.new app_config
And you can call it AppConfig.delivery_time anywhere in the project
Basically for static settings we use following gem
https://github.com/railsjedi/rails_config
so this gem will generate following file
config/settings.yml
you can define your variable(my_config) in this yml file. and use it throughout your application as follows:
Settings.my_config
Or you can use any similar gems
you can use PStore that implements a file based persistence mechanism based on a Hash.
OR
yaml based approach

Where to store (structured) configuration data in Rails

For the Rails 3 application I'm writing, I am considering reading some of the configuration data from XML, YAML or JSON files on the local filesystem.
The point is: where should I put those files? Is there any default location in Rails apps where to store this kind of content?
As a side note, my app is deployed on Heroku.
What I always do is:
If the file is a general configuration file: I create a YAML file in the directory /config with one upper class key per environment
If I have a file for each environment (big project): I create one YAML per environment and store them in /config/environments/
Then I create an initializer where I load the YAML, I symbolize the keys of the config hash and assign it to a constant like APP_CONFIG
I will usually adopt this method :
a config/config.yml
development:
another_key: "test"
app_name: "My App"
test:
another_key: "test"
production:
prova: "ciao"
then create a ostruct in a initializer
#config/initializer/load_config.rb
require 'ostruct'
config = OpenStruct.new(YAML.load_file("#{RAILS_ROOT}/config/config.yml"))
::AppSetting = OpenStruct.new(config.send(RAILS_ENV))
No DB table, per environment setup and you could retrive info in a simple way
AppSetting.another_key
AppSetting.app_name
here a reference
have a nice day!
You can also include it in a model so you can call Settings.var_name from anywhere in your app and it will parse the file for the right environment.
With settingslogic gem:
class Settings < Settingslogic
source "#{Rails.root}/config/settings.yml"
namespace Rails.env
end
Rails creates a config directory by default, containing a lot of configuration info for your application, including the database and environment information. I think that's a logical first place to consider.
A second choice would be the app directory, which contains all the models, views and controllers for the application, but I think of that directory as containing executable code and its templates, so I'd go with the config directory, personally.

How do i define a second environment.rb file in rails?

My default environment.rb is overflowing, and i would like to have a separate file that works exactly the same way. How can I do so?
You're likely adding things to the environment file that should be in an initializer. Check the config/initializers directory for some examples of what to put in there. That should allow you to break things up and make everything more organized.
Rails actually uses eval to load the special environment files such as config/environments/development.rb. This is the code it uses:
eval(IO.read(configuration.environment_path), binding, configuration.environment_path)
You could define a method such as load_more_environment like this:
def load_more_environment(path)
eval(IO.read(path), binding, path)
end
The first argument to eval is just the code you want to load and it will be executed within the current binding. The third argument will be used to report syntax errors in the file.

ActionMailer password security

Am I crazy, or is it a bad idea to keep my SMTP username and password for ActionMailer in the actual (development/production) config file? It seems like I should store it an encrypted place, or at the very minimum, exclude it from my Mercurial pushes.
Right now, I'm just removing the password from my source file before performing a push, but there's got to be a smarter way than the one I'm using. :)
Perhaps I should store it in my database as another user (which is already stored with encrypted passwords) and fetch it programatically?
Use an application configuration file that is not stored in your repository for storing sensitive information. Here is how I've done it:
Add an app_config.yml in your config directory. Its contents would look like this:
smtp_password: kl240jvfslkr32rKgjlk
some_other_password: 34hg9r0j0g402jg
and_so_on: lkn$#gJkjgsFLK4gaj
Add a preinitializer.rb in your config directory with the following contents:
require 'yaml'
APP_CONFIG = YAML.load(File.read(RAILS_ROOT + "/config/app_config.yml"))
Substitute your passwords for values in the APP_CONFIG variable, like so:
smtp_password = kl240jvfslkr32rKgjlk # old version
smtp_password = APP_CONFIG['smtp_password'] # new version
Make sure you don't include app_config.yml in your repository, though you may want to create an example file that is checked in, just to show a sample of what should be in it. When you deploy your application, make sure that app_config.yml is stored on the server. If you're using a standard Capistrano deployment, put the file in the shared folder and update your deployment task to create a symlink to it in the current release's directory.
Jimmy's answer is perfect (+1), I would also note that Github has recommended .gitignore files for every language and the Rails one is here Note that it includes config/*.yml so that no config/yml file is in the respository to begin with. Probably a good move.
Use Capistrano to ask for these things upon deploy:setup the same way you should be doing for your database stuff:
task :my_silly_task do
sendgrid_password = Capistrano::CLI.password_prompt("Sendgrid password: ")
require 'yaml'
spec = {... whatever yaml you need -- probably what Jimmy said...}
run "mkdir -p #{shared_path}/config"
put(spec.to_yaml, "#{shared_path}/config/mailer_config.yml")
end

Resources