Этот бит кажется избыточным:
@resource = {}
@voters = {}
@is_upvoted = {}
Поскольку вы уже зацикливаете массив для выполнения метапрограммирования.
Вы можете попробовать что-то вроде:
class Foo
%w(
resource
voters
is_upvoted
).each do |attr_sym|
define_method attr_sym do |comment|
instance_variable_set("@#{attr_sym}", {}) unless instance_variable_get("@#{attr_sym}")
instance_variable_get("@#{attr_sym}")[comment.id]
end
end
end
Что, я считаю, даст вам методы, примерно такие:
class Foo
def resource(comment)
@resource ||= {}
@resource[comment.id]
end
end
Лично мне кажется, что не очень хорошо иметьcomment.id
в вашем методе. Потому что, если когда-нибудь вы захотите использовать другой атрибут (или что-то совсем другое) в качестве key
?
Итак, я думаю, я бы сделал:
class Foo
%w(
resource
voters
is_upvoted
).each do |attr_sym|
define_method attr_sym do |key|
instance_variable_set("@#{attr_sym}", {}) unless instance_variable_get("@#{attr_sym}")
instance_variable_get("@#{attr_sym}")[key]
end
end
end
Теперь, кажется,как будто вам нужен простой способ установить пары ключ-значение в вашей переменной экземпляра, так что, я думаю, я бы попробовал что-то вроде:
class Foo
%w(
resource
voters
is_upvoted
).each do |attr_sym|
define_method attr_sym do |key=nil|
instance_variable_set("@#{attr_sym}", {}) unless instance_variable_get("@#{attr_sym}")
hsh = instance_variable_get("@#{attr_sym}")
return hsh[key] if key
hsh
end
end
end
В этом случае вы должны быть в состоянии сделать это (при условииу вас есть переменная @comment
, которая отвечает на id
):
@comment.id
=> 1
foo = Foo.new
=> #<Foo:0x000056536d7504b0>
foo.resource
=> {}
foo.resource[@comment.id] = :bar
=> :bar
foo.resource
=> {1=>:bar}
foo.resource[@comment.id]
=> :bar