6

初期化時に 1 ~ 8 個のパラメーターを取る単純なクラスがあります。アクセサーをこれらに設定して、後で使用します。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

サイズを小さくすることについての私の唯一の考えは、初期化時にすべての 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

しかし、これはちょっと弱いようです。

4

2 に答える 2

5

あなたがやろうとしていることを達成する方法の1つを次に示します。

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

Hash#fetchメソッドを確認してください。

pまた、変数のキーと値のペアにアクセスするために使用することもできます@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>
于 2016-01-14T14:15:19.323 に答える
2

それらのそれぞれを異なる変数として割り当てるべきではありません。それを単一のハッシュとして変数に保存し、値が必要なときにハッシュにアクセスする必要があります。実際、すでに変数を持っているようですp。したがって、そのままにしておき@p = pます。

于 2016-01-14T14:15:28.603 に答える