Reputation: 11890
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.
How do I set the constant in this scenario?
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
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