ActiveRecord の attribute 更新方法まとめ

  • 367
    Like
  • 2
    Comment
More than 1 year has passed since last update.

ActiveRecord の attribute 更新方法ってどんなものがあって、それぞれどんな違いがあるかご存じですか?

案外色々とあったので表にまとめてみました。リファレンスやソースコードを参考にしつつ、Rails 4.2 でテストしています。

単一の attribute 更新

メソッド 保存 バリデーション(*1) コールバック(*2) readonly チェック(*3) updated_at の更新 補足 使用例
attribute= x - - - - article.title = 'title'
write_attribute x - - - - private メソッド。attribute= はこれを呼び出している。タイプキャストを行う。例えば integer なカラムの attribute に "5" を渡すと数値の 5 に変換する。 write_attribute(:title, 'title') write_attribute(:rate, "5")
self[:attribute] x - - - - write_attribute の alias。こちらは public。 article[:title] = 'title'
raw_write_attribute x - - - - private メソッド。渡された値のタイプキャストを行わない。例えば integer なカラムの attribute に "5"を渡しても数値の 5 に変換しない。 raw_write_attribute(:title, 'title'), raw_write_attribute(:rate, "5")
update_attribute o x o o o dirty な attribute をすべて保存する。readonly な attribute の場合は例外が発生する。 article.update_attribute(:title, 'title')
update_column o x x o x update_columns(name => value) に相当。詳細については次の表へ。 article.update_column(:title, 'title')

複数の attribute をまとめて更新

メソッド 保存 バリデーション(*1) コールバック(*2) readonly チェック(*3) updated_at の更新 補足 使用例
assign_attributes x - - - - article.assign_attributes(title: 'title', body: 'body')
attributes= x - - - - assign_attributes の alias article.attributes = { title: 'title', body: 'body' }
update o o o o o save を呼び出す article.update(title: 'title', body: 'body')
update_attributes o o o o o update の alias article.update_attributes(title: 'title', body: 'body')
update! o o o o o update と同じ処理を行うが、save ではなく save! を呼び出す。そのため例外が発生する。 article.update!(title: 'title', body: 'body')
update_attributes! o o o o o update! の alias article.update_attributes!(title: 'title', body: 'body')
update_columns o x x o x UPDATE SQL を発行して DB を更新するため最も速い。新しいオブジェクトの場合は例外が発生する。readonly の attribute が更新対象に含まれる場合は例外が発生する。 article.update_columns(title: 'title', body: 'body')

クラスメソッド

メソッド 保存 バリデーション(*1) コールバック(*2) readonly チェック(*3) updated_at の更新 補足 使用例
update o o o o o readonly な attribute を指定すると無視される Article.update([1, 2], [{ title: 'title1', body: 'body1' }, { title: 'title2', body: 'body2' }])
update_all o x x x x 対象のリレーション中すべてのレコードに対して UPDATE SQL を発行する。ActiveRecord のインスタンスを作成しないためバリデーションやコールバックの呼び出し、タイプキャストなどは行われない。そのため、そのまま DB に保存して良い値しか渡すべきではない。 Article.where(category: 'rails').update_all(title: 'title', body: 'body')

(1) 保存時にバリデーションが行われるかどうか。
(*2) 保存時に各種コールバックが呼び出されるかどうか。
(
3) attr_readonly で指定した readonly な attribute が更新されない場合は o。される場合は x。


何かミスにお気づきの際はコメントしていただけると助かります。