Using application-wide variables in Rails 4

Adler @ 2015-09-16


Rails offers various ways to implement methods, but implementing global variables is not as straightforward. Currenly threre are several approaches.

Using application.rb

One Solution on Stackoverflow is to put them in config/application.rb as follow:

module MyAppName
  class Application < Rails::Application
    YOUR_GLOBAL_VAR  = "test"
  end
end

It is fine, but that breaks the entity of the file. Since custom global variables meaning custom business logic, it would be better to put them into a separate file.

Gem figaro & simpleconfig

Another method is to depend on gems. Both Simpleconfig and Figaro offers a good way to configure variables in a different logic. I didn't use simpleconfig before, but I did use Figaro, which is quite handy.

Basically, Figaro creates an config/application.yml file and you store variables for different environments like:

development:
  key: "ad69caf9a44dcac1fb28"
  secret: "83ca7aa160fedaf3b350"

test:
  key: "ad69caf9a44dcac1fb28"
  secret: "83ca7aa160fedaf3b350"

And retrieve the variables like:

Env['key']

It somehow simulates the way we manage variables in Bash or Zsh, which I don't think is neat and straightforward.

Using initializers

Rails loads all files in config/initializers/ folder, which is a good place to init application-wide variables here. For instance, we can create a file business.rb under the initializers directory:

module Business
  class Logic
    Here = "hello world"
  end
end

Business::Logic::Here
# => 'hello world'

Filename and module name can be anything. I suggest use something directly related to the business logic as the module name, like your company name or what. It offers better understanding when reading the code.

Thus you can use it anywhere, in controllers, for example:

class ApplicationController < ActionController::Base
  # Prevent CSRF attacks by raising an exception.
  # For APIs, you may want to use :null_session instead.
  protect_from_forgery with: :exception

  def set_logic
    @logic ||= Business::Logic::Here
  end
end

or in any file in the project.

One bad thing is that we have to restart server at any change in this file since it is only 'initialized' at server start.

However, using initializers ensure the scope of different variables are in the same class, and we can create different files, modules, and classes for variables in different scopes. I believe this is the best way to manage application-wide variables so far.