Ruby on rails Ruby和Rails:元编程变量成为类方法

Ruby on rails Ruby和Rails:元编程变量成为类方法,ruby-on-rails,ruby,model,metaprogramming,instance-variables,Ruby On Rails,Ruby,Model,Metaprogramming,Instance Variables,我正在创建一个名为Configuration的模型,我有以下代码,我希望通过使用元编程使它更具动态性 在配置模型数据库的一个表中,我有以下数据 --------------------------------------------------------- variable_name as string | value in text | company_name | MyCompany welc

我正在创建一个名为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

----------------------------------------------------------
我认为这是一种不可接受的做事方式。首先,每次有人检查公司名称时,它都会访问数据库。我想如果我可以在应用程序启动时加载它,而不必再次访问它,因为它在内存中,那么它会更好。我如何才能做一些更具动态性的事情,以便像这样访问“MyCompany”的价值

Configuration.company_name

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

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
如果您需要大量的配置参数,那么通过访问初始值设定项文件中的配置参数来预加载缓存可能是有益的。如果您有1000个配置变量,您可能需要考虑将缓存迁移到<代码> MycCache 等

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

class Configuration  < ActiveRecord::Base

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

end
如果您需要大量的配置参数,那么通过访问初始值设定项文件中的配置参数来预加载缓存可能是有益的。如果您有1000个配置变量,您可能需要考虑将缓存迁移到<代码> MycCache 等

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

class Configuration  < ActiveRecord::Base

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

end

这里有一件事你弄错了,那就是永远不会是
Configuration.company\u name
,这就像访问属性而不是对象/实例属性


它应该是配置类的一个实例。在另一个答案中使用@KandagaBoggu的方法在某种程度上还是可以接受的,但是数据库访问仍然几乎每次都可以,或者从活动记录的查询缓存中访问。但是AR的查询缓存在特定操作(即请求)期间有效。您可能希望使用Memcached之类的东西使对象存活更长时间

这里有一件事你弄错了,那就是永远不会是
Configuration.company\u name
,这就像访问属性而不是对象/实例属性


它应该是配置类的一个实例。在另一个答案中使用@KandagaBoggu的方法在某种程度上还是可以接受的,但是数据库访问仍然几乎每次都可以,或者从活动记录的查询缓存中访问。但是AR的查询缓存在特定操作(即请求)期间有效。您可能希望使用Memcached之类的东西使对象存活更长时间

我们可以将这些常量值移动到
yml
文件中,当服务器开始将它们加载到变量中并在需要时访问它。

我们可以将这些常量值移动到
yml
文件中,当服务器开始将它们加载到变量中并在需要时访问它。

您确定这真的是个问题吗?Rails非常擅长缓存对数据库的请求,所以我不希望每次有人想要公司名称时都会进行数据库查询。正如著名的Donald Knuth所说:“过早优化是万恶之源”。我认为这是问题的一部分。当我检查production.log时,它一直向MySQL发送请求,这并不理想。主要问题是作为类方法访问变量,而不是通过变量或where(“variable=?”,variable)获取find_,这很难看。你确定这真的是个问题吗?Rails非常擅长缓存对数据库的请求,所以我不希望每次有人想要公司名称时都会进行数据库查询。正如著名的Donald Knuth所说:“过早优化是万恶之源”。我认为这是问题的一部分。当我检查production.log时,它一直向MySQL发送请求,这并不理想。主要问题是作为类方法访问变量,而不必通过变量或where(“variable=?”,variable)获取find_,这很难看。@chim的用例是单例模式的有效候选。查看
Rails
模块。或者太阳黑子库中的配置类:。谢谢!是的,db是可以访问的,但是由于配置变量的范围和数量在这个阶段发生了变化,我认为现在这是一个不错的折衷方案。一旦我的变量变得更“稳定”,我可能会在基于模型的初始化中生成一个配置文件。@Kandaboggu是的,我也这么认为,但我不完全确定他是否会选择“singleton”。在这种情况下,我的错。@chim的用例是singleton模式的有效候选。查看
Rails
模块。或者太阳黑子库中的配置类:。谢谢!是的,db是可以访问的,但是由于配置变量的范围和数量在这个阶段发生了变化,我认为现在这是一个不错的折衷方案。一旦我的变量变得更“稳定”,我可能会在初始化过程中根据模型生成一个配置文件。@kandaboggu是的,我也这么认为,但我不完全确定他会选择“Singelton”。在这种情况下,我的错。非常感谢!两种方法都非常有效。我尝试过使用define_singleton_方法和define_方法,但它只在控制台中起作用,在rails应用程序中不起作用。非常感谢!两种方法都非常有效。我尝试使用define_singleton_方法和define_方法,但它只在控制台中工作,在rails应用程序中不起作用。这是个好主意,但产品的范围正在改变,因此我需要动态创建配置变量,并在运行时访问它们。谢谢这是个好主意,但是产品的范围正在改变,所以我需要动态创建配置变量,并在运行时访问它们。谢谢
class Configuration  < ActiveRecord::Base

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

end
Configuration.company_name