Ruby和Rails:Metaprogramming变量成为类方法

Chi*_*Kan 1 ruby model metaprogramming ruby-on-rails instance-variables

我正在创建一个名为Configuration的模型,我有以下代码,我想通过使用元编程使其更具动态性.

在配置模型的数据库表中,我有以下数据.

---------------------------------------------------------
variable_name as string     |  value in text
                            |
company_name                |  MyCompany
welcome_text                |  Welcome to MyCompany's App!
email_order_text            |  You've just created an account with MyCompany.
year_since                  |  2012
----------------------------------------------------------

class Configuration  < ActiveRecord::Base

    #nothing here yet

end

----------------------------------------------------------
Run Code Online (Sandbox Code Playgroud)

目前,访问company_name的唯一方法是在rails控制台中执行以下操作:

configuration_company_name = Configuration.find_by_variable_name("company_name")
configuration_company_name.company_name

> "MyCompany"
Run Code Online (Sandbox Code Playgroud)

我认为这是一种不可接受的做事方式.首先,每次有人检查公司名称时,它都会访问数据库.我想如果我可以在应用程序启动时加载它并且不必再次访问它,因为它在内存中,那么它会更好.我怎样才能做更动态的事情,所以我可以像这样访问"MyCompany"这个值.

Configuration.company_name

> "MyCompany"
Run Code Online (Sandbox Code Playgroud)

这样做的原因是允许快速定制应用程序.

Har*_*tty 5

class Configuration  < ActiveRecord::Base
  # loads all the configuration variables to an in-memory
  # static hash during the first access. 
  def self.[](n)
    @config ||= {}.tap { |h| Configuration.all.each{ h[variable_name] = c.value}}
    @config[n]
  end
end
Run Code Online (Sandbox Code Playgroud)

现在您可以访问您的配置:

Configuration["company_name"]
Run Code Online (Sandbox Code Playgroud)

如果您有大量配置参数,则通过访问初始化文件中的配置参数来预加载缓存可能会有所帮助.如果您有1000个配置变量,则可能需要考虑将缓存迁移到其他位置memcached.

如果要以类方法的形式访问配置参数:

class Configuration  < ActiveRecord::Base

 klass = class << self; self; end
 Configuration.all.each{|c| klass.send(:define_method, c.variable_name){c.value}}

end
Run Code Online (Sandbox Code Playgroud)

现在您可以按如下方式访问参数:

Configuration.company_name
Run Code Online (Sandbox Code Playgroud)