activerecord如何知道执行插入或更新?

也许一些ruby专家可以在调用save()时了解activerecord如何知道插入或更新。 它背后的逻辑是什么? 它检查主键是否为空或其他什么,如果是,是否插入,如果不是更新?

虽然对某些人说“RTFM”很好,但我更倾向于使用Rails-3-come-out-and-changes-everything响应:

它如何在Rails 2.3中工作(又名“今天”)

save调用create_or_update ,如下所示:

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

您可以忽略此方法的第一行,因为如果记录是只读的,它只会引发错误(通常不是,但在连接的情况下可能是这样)。 我们在这里感兴趣的是方法内的第二行和第三行。

第二行调用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 

并且当initializenew调用initialize ,并给我们一个新对象,这里有一些后台Ruby-fu)方法调用时,设置变量@new_record

因此,如果这个@new_recordtrue它将调用create ,如果它是false,它会调用update ,这会让我们看到你所追求的东西,我想。

此外,当您找到记录时,它不会调用initialize ,因此不会设置@new_record 。 如果你注意到, new_record?背后的代码new_record?@new_record || false @new_record || false ,表示如果未设置@new_record ,它将返回false。

比如说你想找到最后一个Forum记录,所以你会做Forum.last

  1. 这将调用Forum类中的last方法,该方法inheritance自ActiveRecord :: Base
  2. last 调用 find类方法。
  3. find 调用 find_last
  4. find_last 调用 find_initial
  5. find_initial 调用 find_every
  6. find_every 调用 find_by_sql
  7. find_by_sql调用instantiate

你会在这里看到,在这个变化中没有任何地方是@new_record set,因此find获得的任何记录都不会是新记录。

希望这有助于您理解。

它主要依赖于new_record? 方法。
如果它是新记录,则此方法返回true,否则返回false。

事实上,这并不难。

  • 当你获得现有记录时,它并不是新的。 那么new_record? 可以直接返回虚假。
  • 当你创建一个新记录( Model.new ), new_record? 将返回true。 这是一项新纪录。
  • 保存新记录时,它不再是新记录了。 内部变量@new_record得到更新。 new_record? 将不会再回归真实。

要查看它何时发生,请转到ActiveRecord :: Base ,第2911行

  self.id ||= new_id @new_record = false id end 

查看activerecord的doc以及那里的源代码。