分配分支条件太高

Car*_*lyL 6 ruby coding-style rubocop

我有一个简单的类,在初始化时,需要一到八个参数.它将访问器设置为稍后使用.Rubocop正试图逮捕我,因为ABC太高了,但我不确定我所做的事情是否真的有问题.这是我刚刚在初始化时禁用检查的情况吗?

class Foo
  attr_accessor :one, :two, :three, :four
  attr_accessor :five, :six, :seven, :eight

  def initialize(p={})
    @one = p[:one] if p[:one].present?
    # ...
    @eight = p[:eight] if p[:eight].present?
  end
end
Run Code Online (Sandbox Code Playgroud)

我对减小大小的唯一想法是做一些事情,比如在初始化时迭代我的所有attr_accessors,看看是否在has中传递了相应的符号,如果是这样的话.

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
Run Code Online (Sandbox Code Playgroud)

但这似乎有点弱.

And*_*eko 5

这是实现您正在尝试做的事情的方法之一:

class Foo
  attr_accessor(*%i[one two three four five six seven eight])

  def initialize(p = {})
    p.keys.each { |k| instance_variable_set("@#{k}", p.fetch(k, nil)) }
  end
end
Run Code Online (Sandbox Code Playgroud)

查看Hash#fetch方法。

p如果您决定使用一个 ( @p)而不是 8 个变量,您也可以使用它来仅访问变量的键值对


编辑

只是出于好奇写了这个版本(使用了一些元编程) - 它会动态添加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
Run Code Online (Sandbox Code Playgroud)

发生的事情是,我们将提供给initialize方法参数 (hash p),获取其键并从中创建实例变量,为每个变量分配与键对应的值。然后我们attr_accessor为每个键定义。

a = Foo.new(a: 2, b: 3)
#=> #<Foo:0x00000002d63ad8 @a=2, @b=3>
Run Code Online (Sandbox Code Playgroud)