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
并且当initialize
( new
调用initialize
,并给我们一个新对象,这里有一些后台Ruby-fu)方法调用时,设置变量@new_record
。
因此,如果这个@new_record
为true
它将调用create
,如果它是false,它会调用update
,这会让我们看到你所追求的东西,我想。
此外,当您找到记录时,它不会调用initialize
,因此不会设置@new_record
。 如果你注意到, new_record?
背后的代码new_record?
是@new_record || false
@new_record || false
,表示如果未设置@new_record
,它将返回false。
比如说你想找到最后一个Forum
记录,所以你会做Forum.last
。
- 这将调用
Forum
类中的last
方法,该方法inheritance自ActiveRecord :: Base -
last
调用find
类方法。 -
find
调用find_last
-
find_last
调用find_initial
-
find_initial
调用find_every
-
find_every
调用find_by_sql
- 和
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以及那里的源代码。