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
なるほど...。