Как activerecord знает, как выполнить вставку или обновление?

Возможно, некоторые эксперты по рубину могут пролить свет на то, как activerecord знает, как сделать вставку или обновление при вызове save(). Какова его логика? проверяет ли он, что первичный ключ пуст или что-то еще, и если это так, то вставка, если не обновление?

Ответы

Ответ 1

Несмотря на то, что некоторые люди говорят "RTFM", я предпочитаю более полный ответ, но все же полностью бесполезный-когда-Rails-3-выходы-и-изменения -все ответ:

Как это работает в Rails 2.3 (ака "сегодня" )

save вызывает create_or_update, который выглядит например:

def create_or_update
  raise ReadOnlyRecord if readonly?
  result = new_record? ? create : update
  result != false
end

Вы можете игнорировать первую строку этого метода, поскольку она вызывает только ошибку, если запись является readonly (обычно это не так, но в случае присоединений она может быть). Здесь нас интересует вторая и третья линии внутри метода.

Вторая строка вызывает new_record?, которая определяется следующим образом:

  # Returns true if this object hasn't been saved yet -- that is, a record for the object doesn't exist yet; otherwise, returns false.
  def new_record?
    @new_record || false
  end

И переменная @new_record устанавливается, когда initialize (new вызывает initialize) и дает нам новый объект, вызывается какой-то фоновый Ruby-fu здесь).

Итак, если этот @new_record равен true, он вызовет create, и если он будет ложным, он вызовет update, который, как мне кажется, приводит нас к тому, что вы после.

Кроме того, когда вы находите запись, она не вызывает initialize и поэтому не устанавливает @new_record. Если вы заметили, то код new_record? был @new_record || false, то есть он вернет false, если @new_record не был установлен.

Скажем, например, вы хотите найти последнюю запись Forum, поэтому вы бы сделали Forum.last.

Вы увидите здесь, что нигде в этом изменении не установлено @new_record, и поэтому любая запись, полученная с помощью find, не будет новой записью.

Надеюсь, это поможет вам понять.

Ответ 2

Это принципиально зависит от метода new_record?.
Этот метод возвращает true, если это новая запись и false, если это не так.

На самом деле это не очень сложно.

  • Когда вы получаете существующую запись, она не новая. Поэтому new_record? может возвращать false false.
  • Когда вы создаете новую запись (Model.new), new_record? вернет true. Это новая запись.
  • Когда вы сохраняете новую запись, она не является новой. Внутренняя переменная @new_record обновляется. new_record? больше не вернется.

Чтобы узнать, когда это произойдет, перейдите к ActiveRecord:: Base, строка 2911

    self.id ||= new_id

    @new_record = false
    id
  end

Ответ 3

Отметьте activerecord doc здесь и исходный код там.