Rubyでオブジェクトをハッシュ化して特定のkeyを取り除いて新たなハッシュを返す

こんにちは!kossyです!



さて、今回は、Rubyでオブジェクトをハッシュ化して特定のkeyを取り除いて新たなハッシュを返す方法について、
ブログに残してみたいと思います。







下記のようなオブジェクトがあるとします。

=> #<Article:0x00007fe76b8d89c0
 id: 1,
 title: "練習試合の結果0",
 body:
  "Morning Gloryが4対2でSunflowerに勝利。\n\n2回表、6番渡辺の二塁打から7番山田、8番高橋の連続タイムリーで2点先制。9回表、ランナー一二塁で2番田中の二塁打で2点を挙げ、ダメを押しました。\n\n投げては初先発の山本が7回を2失点に抑え、伊藤、中村とつないで逃げ切りました。",
 released_at: Sat, 22 Jun 2019 12:02:35 JST +09:00,
 expired_at: Fri, 28 Jun 2019 12:02:35 JST +09:00,
 member_only: true,
 created_at: Sun, 30 Jun 2019 12:02:35 JST +09:00,
 updated_at: Sun, 30 Jun 2019 12:02:35 JST +09:00>

このオブジェクトをハッシュ化したい場合、
attriburesメソッドを使うと、ハッシュ化できます。

rails/attribute_methods.rb at master · rails/rails · GitHub

pry(main)> article.attributes
=> {"id"=>1,
 "title"=>"練習試合の結果0",
 "body"=>
  "Morning Gloryが4対2でSunflowerに勝利。\n\n2回表、6番渡辺の二塁打から7番山田、8番高橋の連続タイムリーで2点先制。9回表、ランナー一二塁で2番田中の二塁打で2点を挙げ、ダメを押しました。\n\n投げては初先発の山本が7回を2失点に抑え、伊藤、中村とつないで逃げ切りました。",
 "released_at"=>Sat, 22 Jun 2019 12:02:35 JST +09:00,
 "expired_at"=>Fri, 28 Jun 2019 12:02:35 JST +09:00,
 "member_only"=>true,
 "created_at"=>Sun, 30 Jun 2019 12:02:35 JST +09:00,
 "updated_at"=>Sun, 30 Jun 2019 12:02:35 JST +09:00}


$ article.attributes.class
=> Hash

ハッシュ化したあと、特定のkeyを取り除いて新たなハッシュを作成したい場合は、
reject(またはdelete_if)を使います。

$ article.attributes.reject{|key| ['id', 'body', 'released_at', 'expired_at', 'created_at', 'updated_at'].include?(key) }
=> {"title"=>"練習試合の結果0", "member_only"=>true}


特定のkeyを取り除いて、新たなハッシュを返すことができました。

rejectにブロック引数を複数渡すこともできます。
例えば、特定のkeyを取り除きつつ、valuenilの値を取り除きたいとします。

=> #<Article:0x00007fe76b8d89c0
 id: 1,
 title: "練習試合の結果0",
 body:
  "Morning Gloryが4対2でSunflowerに勝利。\n\n2回表、6番渡辺の二塁打から7番山田、8番高橋の連続タイムリーで2点先制。9回表、ランナー一二塁で2番田中の二塁打で2点を挙げ、ダメを押しました。\n\n投げては初先発の山本が7回を2失点に抑え、伊藤、中村とつないで逃げ切りました。",
 released_at: Sat, 22 Jun 2019 12:02:35 JST +09:00,
 expired_at: nil,
 member_only: true,
 created_at: Sun, 30 Jun 2019 12:02:35 JST +09:00,
 updated_at: Sun, 30 Jun 2019 12:02:35 JST +09:00>

$ article.attributes.reject{|k, v| ['id', 'body', 'released_at', 'created_at', 'updated_at'].include?(k) || v.nil?}

include?やnil?メソッドを駆使して、目的を達成することができました。

Rubyってほんと書きやすいですね。