在 ruby 中动态定义 memoized getter

Define memoized getter dynamically in ruby

使用Ruby,我想在相应的getter中动态创建class级的实例变量。对于其中两个,我使用 attr_reader。但是对于那些需要初始化为空数组的,我做了以下操作:

class MatchMake
  class << self
    attr_reader :local_data, :remote_data
    ["type1", "type2"].each do |elem|
      define_method "#{elem}_matches".to_sym do
        instance_variable_set("@#{elem}_matches", [])
      end
    end
  end
  ...
end

根据我的理解,这段代码等同于:

class MatchMake
  class << self
    def local_data
      @local_data
    end
    def remote_data
      @remote_data
    end
    def type1_matches
      @type1_matches = []
    end
    def type2_matches
      @type2_matches = []
    end
  end
  ...
end

首先我想知道我的理解是否正确。其次,我想知道是否有一种方法可以记忆变量,如下所示:

def type1_matches
  @type1_matches ||= []
end

首先,你定义的是type1_matches,而不是type1。其次,define_method接受字符串,#to_sym是多余的。最后但并非最不重要的一点是,您将 getter 定义为实际上 setter。因此,根据需要定义 type1

define_method "#{elem}=", value do
  instance_variable_set("@#{elem}", value)
end

现在,对于 getter,延迟实例化为空数组:

define_method "#{elem}" do
  instance_variable_set("@#{elem}", []) \
      unless instance_variable_defined?("@#{elem}")
  instance_variable_get("@#{elem}")
end

下面是我为 use-cases 编写的示例模式: https://gist.github.com/ritikesh/09384fec25c4b05cfdec8674ce3a9076

这是其中的代码:

# memoize db/cache results in instance variable dynamically
def memoize_results(key)
  return instance_variable_get(key) if instance_variable_defined?(key)
  instance_variable_set key, yield  
end

# usage
MY_CONSTANT = [:active, :inactive]
MY_CONSTANT.each { |key|
  define_method("#{key}_users") do
    memoize_results("@#{key}_users") do
      User.send(key).all # assumes that user responds to active, inactive(via scope/filter etc..)
    end
  end
}