我有一个简单的类,在初始化时需要一到八个参数。它将访问器设置为稍后使用。 Rubocop正试图逮捕我,因为ABC太高了,但我不确定我所做的事情是否真的有问题。这是我刚刚在初始化时禁用检查的情况吗?
class Foo
attr_accessor :one, :two, :three, :four
attr_accessor :five, :six, :seven, :eight
def initialize(p={})
instance_variables.each do |variable|
send("@#{variable}") = p["#{send(variable)}".to_sym] if p["#{send(variable)}".to_sym].present?
end
end
end
我对缩小大小的唯一想法是做一些事情,比如在初始化时迭代我的所有attr_accessors,看看是否在has中传递了相应的符号,如果是这样的话。
{{1}}
但这似乎有点弱。
答案 0 :(得分:4)
这是实现您想要做的事情的方法之一:
class Foo
%i(one two three four five six seven eight).each { |attribute| attr_accessor attribute }
def initialize(p = {})
p.keys.each { |k| instance_variable_set("@#{k}", p.fetch(k, nil)) }
end
end
查看Hash#fetch
方法。
您还可以使用它来访问p
变量的键值对,如果您不是8个变量决定使用其中一个(@p
)
出于好奇而写了这个版本(使用了一些元编程) - 它会为添加的实例变量动态添加attr_accessor
:
class Foo
def initialize(p = {})
p.keys.each do |k|
instance_variable_set("@#{k}", p.fetch(k, nil))
self.class.__send__(:attr_accessor, k)
end
end
end
发生了什么,是我们提供给initialize
方法参数(hash p
),获取它的键并从中创建实例变量,为每个变量分配与键对应的值。然后我们为每个键定义attr_accessor
。
a = Foo.new(a: 2, b: 3)
#=> #<Foo:0x00000002d63ad8 @a=2, @b=3>
答案 1 :(得分:2)
您不应将每个变量分配为不同的变量。您应该将其作为单个哈希保存到变量中,并在需要值时访问哈希。实际上,您似乎已经拥有变量p
。因此请将其保留为@p = p
。