Where to keep large constant Hash

Viewed 312

We have exports. In order to create those exports we have a list(basically a big constant hash) of column names.

def columns
{ nm: 'person name',
  age: 'person age',
  sex: 'person gender'...}
end

note: the actual hash is about 20-60 elements long depending of the export type and that there are multiple exports.

The question is where should this hash be placed ?

From my research I found a few options:

it seems that this gem: https://github.com/rubyconfig/config would do the trick. but it's purpose seem to be a bit removed from my own. Taking that idea and creating a simple .yml file would be better. But then arises the question where should this .yml be placed in the context of the rails file structure ?

Another option would be to create a class or a module with the sole purpose of returning this hash. Then again where should this class/module be placed in the context of the rails file structure ?

What would be the most rails way to do this?

1 Answers

The way I handle this type of constant depends on the nature of the constant... if it's a site-wide constant, I'll put it in lib/constants.rb, which is my file for all such site-wide constants. Or if you don't like putting them all in one file, you can put them in separate files. The lib/xx.rb files must be included at boot time, so in config/application.rb I put:

# config/application.rb
begin
  require File.expand_path('../../lib/constants', __FILE__)
rescue LoadError
end

Note I'm use Ruby, not yaml, so the lib/constants.rb includes:

# lib/constants.rb
EXPORT_COLUMNS={ nm: 'person name',
                 ...
                 etc.
               }

Alternatively if the constant is not site-wide but model-related, I promote the constant to be a class constant:

# app/models/my_model.rb
class MyModel < ApplicationRecord
  EXPORT_COLUMNS = { nm: "person name", .... etc}

  # if you need the hash as an instance method
  def columns
    EXPORT_COLUMNS
  end
end

And finally, if it just looks too 'ugly' as a class constant, you can include a configuration file. I usually put non-active-record models in app/domain_models/, but if you don't like that, you can put it in lib.

# app/domain_models/export_config.rb
class ExportConfig
  EXPORT_COLUMNS={nm: "person name", ...}
  def columns
    EXPORT_COLUMNS
  end
end

# app/models/my_model.rb
require 'export_config'
class MyModel < ApplicationRecord
  include ExportConfig
end
Related