ActiveRecord::Baseのcreateとsaveの違い
たまたま仕事で気になったので、ActiveRecord::Base
のcreate
とsave
の違いについて簡単に調べました。
まとめ
save(!)
メソッドはcreate(!)
メソッドで利用されているcreate(!)
メソッドはnewメソッドとsave(!)
メソッドを行うメソッドsave(!)
メソッドを利用しているので、レコードの保存に失敗した場合、create
メソッドでは属性が代入されたオブジェクトが返り、create!
メソッドでは例外が発生するsave(!)
メソッドの中を追っていくと、new_record?
メソッドの返り値によって、INSERT文を呼び出しているメソッドとUPDATE文を呼び出しているメソッドを分けている風に見える
save(!)メソッドはcreate(!)メソッドで利用されている
https://github.com/rails/rails/blob/master/activerecord/lib/active_record/persistence.rb より。
def create(attributes = nil, &block) if attributes.is_a?(Array) attributes.collect { |attr| create(attr, &block) } else object = new(attributes, &block) object.save object end end (中略) def create!(attributes = nil, &block) if attributes.is_a?(Array) attributes.collect { |attr| create!(attr, &block) } else object = new(attributes, &block) object.save! object end end
create(!)メソッドはnewメソッドとsave(!)メソッドを行うメソッド
def create!(attributes = nil, &block) if attributes.is_a?(Array) attributes.collect { |attr| create!(attr, &block) } else object = new(attributes, &block) object.save! object end end
save(!)メソッドを利用しているので、レコードの保存に失敗した場合、createメソッドでは属性が代入されたオブジェクトが返り、create!メソッドでは例外が発生する
# 例外が発生しても捉えられているので、 # createのメソッドのコードは続行するため、createメソッドでは # 保存に成功していない状態のオブジェクトが返ってくる def save(*args) create_or_update(*args) rescue ActiveRecord::RecordInvalid false end # 例外が発生する def save!(*args) create_or_update(*args) || raise(RecordNotSaved.new("Failed to save the record", self)) end
save(!)メソッドの中を追っていくと、new_record?メソッドの返り値によって、INSERT文を呼び出しているメソッドとUPDATE文を呼び出しているメソッドを分けている風に見える
save(!)
メソッドの中にあるcreate_or_update(*args)
を探してみる。
def create_or_update(*args) raise ReadOnlyRecord, "#{self.class} is marked as readonly" if readonly? result = new_record? ? _create_record : _update_record(*args) result != false end
なるほど...。