在Rails Initializer中懒惰地定义常量

时间:2015-11-20 02:08:44

标签: ruby-on-rails initializer

我有一个初始化程序,它加载一个YML文件,通过ERB解析它,并将得到的哈希存储在一个可访问应用程序范围的常量

# config/initializers/links.rb

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

ERB的原因是YML文件中的某些元素依赖于URL帮助程序并需要模板化 -

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

问题是,当初始化程序运行时,它会失败,因为Rails环境尚未初始化(我认为?),因此这些帮助程序定义不存在。

为了解决这个问题,我懒洋洋地阅读了这个文件,所以只有在第一次调用它时才会被解析(这可能是在我们加载了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

但现在我收到错误,因为const_set不是定义的方法。

  1. 如何在此方案中设置常量?

  2. 此方法是否确保在第一次调用常量时全局定义常量(即app-wide)?如果从视图/控制器/模型/等中调用links() ...我不希望在该类的上下文中设置该常量。

  3. 谢谢!

1 个答案:

答案 0 :(得分:1)

我认为使用它的原因是性能,我认为更好的是使用CacheStore创建一个辅助方法:

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

然后你应该只在必要时包括这个帮助器,默认情况下不包括它。