ActiveRecord, Mongoidに定義されているupdate_attribute
メソッドはバリデーション無しに値を保存しているようです。これを使ってハマったのでメモしておきます。
調査対象
- ActiveRecord: 4.0.2
- Mongoid: 3.1.6
ActiveRecord
ActiveRecordのlib/active_record/persistence.rb
の該当部分を見てみましょう。
def update_attribute(name, value) name = name.to_s verify_readonly_attribute(name) send("#{name}=", value) save(validate: false) end
処理の最後でsaveメソッドを呼んでいますが、validate: false
になっていますね。
Mongoid
Mongoidのlib/mongoid/persistence.rb
の該当部分を見てみましょう。
def update_attribute(name, value) normalized = name.to_s unless attribute_writable?(normalized) raise Errors::ReadonlyAttribute.new(normalized, value) end write_attribute(database_field_name(normalized), value) save(validate: false) end
こちらも処理の最後でsaveメソッドを呼んでいますが、ActiveRecordと同様にvalidate: false
になっています。(書き込み可能なattributeかどうか判断する処理が両者で異なっているのが興味深いです。今回は深追いしません。)
update_attributes
update_attributes
というメソッドを使うとバリデーションを行ってくれますので、普段はこちらを使うのが安全なのかなと思います。
def update(attributes) # The following transaction covers any possible database side-effects of the # attributes assignment. For example, setting the IDs of a child collection. with_transaction_returning_status do assign_attributes(attributes) save end end alias update_attributes update
Mongoid
def update_attributes(attributes = {}, options = {}) assign_attributes(attributes, options); save end