user2490003
user2490003

Reputation: 11890

Lazily defining constants in a Rails Initializer

I have an initializer which loads a YML file, parses it through ERB, and stores the resulting hash in a constant that's accessible app-wide

# config/initializers/links.rb

LINKS = YAML.load(
  ERB.new(File.read(Rails.root.join("config", "links.yml"))).result
)

The reason for the ERB is that some elements in the YML file rely on URL helpers and need to be templated -

# config/links.yml
---
footer:
  homepage:
    personal: <%= personal_path %>
    root: <%= root_path %>
    foo: bar
    ....

The problem is that when the initializer runs, it fails because the Rails environment has not been initialized (I think?) and so those helper definitions don't exist.

To work around that, I lazily read that file so it only gets parsed when it's called for the first time (which is presumably after we've loaded the environment)

# config/initializers/links.rb

def links
  unless defined? LINKS
    links = YAML.load(
      ERB.new(File.read(Rails.root.join("config", "links.yml"))).result
    )
    const_set("LINKS", links)
  end

  LINKS
end

But now I'm getting an error because const_set is not a defined method.

  1. How do I set the constant in this scenario?

  2. Does this method ensure that the constant is defined globally (i.e. app-wide) the first time it's called? If links() is called from a view/controller/model/etc... I wouldn't want that constant to get set within the context of just that class.

Thanks!

Upvotes: 2

Views: 705

Answers (1)

Mareq
Mareq

Reputation: 1351

I suppose the reason for using that is the performance, I think much better is to create a helper method with CacheStore used:

module LinksHelper
  def links
    Rails.cache.fetch("links_helper/links", expires_in: 1.hour) do
      YAML.load(
        ERB.new(File.read(Rails.root.join("config", "links.yml"))).result
      )
    end
  end
end

and then you should only include this helper when it is necessary and not included by default.

Upvotes: 3

Related Questions