model のインスタンスを hash化する

使う機会はあまり無い気もするが、メモしておく*1


結論から書くと、モデルインスタンス#attributes とするだけ。

model_instance = Model.new
attributes_hash = model_instance.attributes  # {"attr1" => "val1", "attr2" => "val2", ...}
p attributes_hash.class  # --> Hash


どんなとこで使ったのかというと、
同じ名前のカラムを持っている2つの異なるモデルがあるとする。
そのカラムを一方からもう一方にコピーしたいときに、どうやるのがスマートかな、という話し。

# name, attr1 を持つモデルA と name, attr1, attr2 を持つモデルB があったとする
model_a = ModelA.first
model_b = ModelB.new

# 1つ1つ入れるのは、カラム数が少なければいいけど、多いと・・・
model_b.name = model_a.name
model_b.attr1 = model_a.attr1

# ループもいまいち・・
ModelA.column_names.each do |attr_name|
  model_b[attr_name] = model_a[attr_name]
end

# attributes なら一発
model_b = ModelB.new(model_a.attributes)

まぁ、そもそもこんなコピーをしないといけないモデル設計が微妙な可能性もあり。。。

ちなみに、上では「いまいち」とかって書いちゃってるけど、
Model.column_names で全カラム名の入った配列が取れるのも最初は知りませんでしたorz...

p ModelA.column_names  # --> ["name", "attr1"]

*1:rails詳しい人的にはあたり前のことかも?