使用Ruby,我想在相应的getter中动态创建类级实例变量。对于其中两个,我使用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
答案 0 :(得分:2)
首先,您定义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
答案 1 :(得分:2)
以下是我为此类用例编写的示例模式: 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
}