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

时间:2009-11-05 21:27:02

标签: ruby-on-rails

也许有些红宝石专家可以在调用save()时了解activerecord如何知道插入或更新。它背后的逻辑是什么?它是否检查主键是否为空或某些内容,如果是,那么是否为更新?

3 个答案:

答案 0 :(得分:23)

虽然对某些人说“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

initialize@new_record调用new,并为我们提供一个新对象,这里有一些后台Ruby-fu)方法时,设置变量initialize

因此,如果此@new_recordtrue,则会调用create,如果它为假,则会调用update,这会将我们带到您所追求的内容,我认为

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

例如,假设您要查找最后一条Forum条记录,那么您可以执行Forum.last

  1. 这会调用继承自ActiveRecord :: Base的Forum类的last方法
  2. last calls find类方法。
  3. find calls find_last
  4. find_last calls find_initial
  5. find_initial calls find_every
  6. find_every calls find_by_sql
  7. find_by_sql来电instantiate
  8. 您会在此处看到此更改无处设置@new_record,因此find获取的任何记录都不会成为新记录。

    希望这有助于您理解。

答案 1 :(得分:2)

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

事实上,这并不是很难。

  • 当您获得现有记录时,它并不是新记录。所以new_record?可以直接返回false。
  • 当您创建新记录(Model.new)时,new_record?将返回true。这是一项新纪录。
  • 当您保存新记录时,它不再是新记录了。内部变量@new_record会更新。 new_record?将不再返回true。

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

    self.id ||= new_id

    @new_record = false
    id
  end

答案 2 :(得分:1)

查看activerecord的文档here和源代码there