2015-07-03 2 views
1

Используя Ruby, я хочу динамически создавать переменные экземпляра класса на уровне соответствующих геттеров. Для двух из них я использую attr_reader. Но для тех, которые должны быть инициализированы в пустой массив, я следующее:Определить memoized геттер динамически в ruby ​​

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 

Во-первых, я хотел бы знать, если я правильно в моем понимании. Во-вторых, я хотел бы знать, если есть способ memoize переменные, как в следующем примере:

def type1_matches 
    @type1_matches ||= [] 
end 

ответ

2

Прежде всего, вы определяете type1_matches, не type1. Во-вторых, define_method принимает строки, #to_sym является излишним. Последнее, но не менее важное, вы определяете, что геттер фактически является сеттером. Таким образом, чтобы определить type1 как вы хотели:

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

Теперь, добытчика, лениво инстанцирован в пустой массив:

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

Моя ошибка, моя с ode должен прочитать def type1_matches, отредактируйте вопрос, чтобы отразить выше. –

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 
} 
+1

Ссылка на решение приветствуется, но, пожалуйста, убедитесь, что ваш ответ полезен без него: [добавить контекст вокруг ссылки] (// meta.stackexchange.com/a/8259), чтобы у ваших друзей-пользователей было некоторое представление о том, что это такое и почему он там, затем укажите наиболее релевантную часть страницы, на которую вы ссылаетесь, в случае недоступности целевой страницы. [Ответы, которые немного больше, чем ссылка, могут быть удалены.] (// stackoverflow.com/help/deleted-answers) – FelixSFD

+0

Я добавил код, как было предложено. – Ritikesh

Смежные вопросы