【Rails】ハッシュのKEYと同じ名称のカラムに代入するsendメソッド

今日は以下のような事はできないだろうか、と思って調べていました。

ハッシュのKEYと同じ名称のカラムに値を代入したい

結論、sendというメソッドを使ってできたのでそれをまとめています。

sendメソッドを使う目的

ハッシュのKEYと同じ名称のカラムに値を代入したいといっても

何をしたいのかよくわからないと思うのですが、解説すると‥

Userモデルがあってカラム名としてid、name、umare、job、seikaku、girlfriend、boyfriend、syumi1、syumi2、syumi3があるとします。

一方ハッシュには次のようなデータが入っています。

u_hash = {
   'name' => '山田 一郎',
   'umare' => '東京都豊島区',
   'job' => 'エンジニア',
   'girlfriend' => 'いる',
}

これはシンボルでもよくて

u_hash = {
   :name => '山田 一郎',
   :umare => '東京都豊島区',
   :job => 'エンジニア',
   :girlfriend => 'いる',
}

と記述しても良いです。値を取り出すにはu_hash[:umare]とすれば’東京都豊島区’を取得できます。

Userのインスタンスは以下のように生成します。

user = User.new

これで空っぽのuserが生成できました。このuserのname、umare、job、girlfriendに値を代入したいと思います。

user.name = u_hash[:name]
user.umare = u_hash[:umare]
user.job = u_hash[:job]
user.girlfriend = u_hash[:girlfriend]

とすれば代入はできます。けどhashの中身が別な人は以下のようになってるかもしれない。

u_hash = {
   :name => '斉藤 花子',
   :job => '事務',
   :boyfriend => 'いる',
   :syumi1 => '手芸',
}

このときは

user.name = u_hash[:name]
user.job = u_hash[:job]
user.boyfriend = u_hash[:girlfriend]
user.syumi1 = u_hash[:syumi1]

となっちゃう。

項目数は10個程度なら全部書き出して以下のようにしてもいいけど。

user.name = u_hash[:name]
user.umare = u_hash[:umare]
user.job = u_hash[:job]
user.girlfriend = u_hash[:girlfriend]
user.boyfriend = u_hash[:girlfriend]
user.seikaku = u_hash[:seikaku]
user.syumi1 = u_hash[:syumi1]
user.syumi2 = u_hash[:syumi2]
user.syumi3 = u_hash[:syumi3]

この数が非常に多くて大変なので、hashのkeyと同じ名前の変数の部分に値を代入できるようにしたいなというのが今回の目的です。

hashはeachメソッドで

hash.each do |key, value|
end

とすれば、hashの中にある全てのkeyに対して操作ができます。

sendメソッドが使えた、その使い方

こちらにリファレンスがありました。
https://ref.xaio.jp/ruby/classes/object/send

sendメソッドは以下のようにして使えます。

obj.send(name, arg)

objが持っているnameというメソッドを呼び出して、argを引数として渡してあげることができます。

上の例でいくと

user.send('メソッド=’, '値’)

user.send('umare=’, '東京都’)

という書き方ができます。メソッド名文字列の後ろにイコール(=)を付けることで値を設定できます。これはRubyのモデルのカラム名がメソッドとして定義されているからです。

user.umareのumareは実はメソッド(いわゆるセッター)なので、sendメソッドでumareというメソッドを指定することができている、のだと思います。

なので以下のように記述しました。

hash.each do |key, value|
  setter = key.to_s + '='
  user.send(setter, value)
end

keyは文字列じゃなくてシンボルの場合もあるのでto_sで文字列化してその後ろにイコールを付けてsetterに渡しています。

例えばこの人の場合は

u_hash = {
   :name => '斉藤 花子',
   :job => '事務',
   :boyfriend => 'いる',
   :syumi1 => '手芸',
}

これによって各key(name, job, boyfriend, syumi1)の後ろにイコールがついて、(name=, job=, boyfriend=, syumi1=)なります。
このsetterをsendの第1引数に指定してあげてvalueを代入しています。

これで「斉藤 花子」の場合はname、job、boyfriend、syumi1が代入されますが
「山田一郎」の場合はname、umare、job、girlfriendが代入されます。

ということで以上です!