LoginSignup
4
4

More than 5 years have passed since last update.

[改訂版] 2つのオブジェクトをマージする

Last updated at Posted at 2016-06-02

オブジェクトの変数同士をマージしたいことがあったので、その時に書いたコードを共有します。

class A
  attr_accessor [:foo, :bar, :hoge, :baz, :piyo]
  def initialize(initial_props = {})
    initial_props.each do |prop_name, prop_value|
      self.send("#{prop_name}=", prop_value)
    end
  end
  def to_h
    hash = {}
    instance_variables.each do |val|
      if self.send(val.to_s.delete("@"))
        hash[val.to_s.delete("@")] = self.send(val.to_s.delete("@"))
      end
    end
    hash
  end
  def merge(another)
    self.class.new(to_h.merge(another.to_h))
  end
end

initialize

  attr_accessor [:foo, :bar, :hoge, :baz, :piyo]
  def initialize(initial_props = {})
    initial_props.each do |prop_name, prop_value|
      self.send("#{prop_name}=", prop_value)
    end
  end

hashでpropertyを初期化できるようにしておきます。

to_hを定義

  def to_h
    hash = {}
    instance_variables.each do |val|
      if self.send(val.to_s.delete("@"))
        hash[val.to_s.delete("@")] = self.send(val.to_s.delete("@"))
      end
    end
    hash
  end

まずこのto_hメソッドを定義してインスタンス変数をhashとして返せるようにします。このときif文でnilのものはhashに含まないようにします。

mergeを定義

  def merge(another)
    self.class.new(to_h.merge(another.to_h))
  end

続いて上で作成したto_hメソッドを使ってmergeを定義します。中でHash#mergeを使って変数同士をmergeしています。to_hメソッドでnilをhashに含めなかったのはこのHash#mergeを使うためです。そうでないと普通にanother_a_objで上書きする事になってしまいます。マージしたhashから新たにインスタンスを作成して返します

使ってみる

a_1 = A.new({foo: "foo", bar: "bar"})
=> #<A:0x007f953db0e620 @bar="bar", @foo="foo">
a_2 = A.new({hoge: "hoge", baz: "baz"})
=> #<A:0x007f953db24088 @baz="baz", @hoge="hoge">
a_1.merge(a_2)
=> #<A:0x007f953b662d30 @bar="bar", @baz="baz", @foo="foo", @hoge="hoge">

//値が被った場合は引数側で上書きされる
pry(main)> a_1 = A.new({foo: "foo", bar: "bar"})
=> #<A:0x007f953b623680 @bar="bar", @foo="foo">
pry(main)> a_2 = A.new({foo: "foo_modified", baz: "baz"})
=> #<A:0x007f953da9d0b0 @baz="baz", @foo="foom_odified">
pry(main)> a_1.merge(a_2)
=> #<A:0x007f953dad7d50 @bar="bar", @baz="baz", @foo="foo_modified">

うまくいきました!
もっと良いやり方があれば是非ご意見お待ちしていますm
(コメント欄にあるfrom_kyusyuさんにコメント頂きましたコードでエラー処理もされたより良いものも書いてありますのでそちらもご覧ください。)

4
4
2

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4
4