为什么ActiveRecord不够聪明,不知道父亲的object_id应该等于其子节点的父节点的object_id?

问题描述 投票:4回答:5
  @father = Hierarchy.find(:first, :conditions => ['label = ?', 'father'])

  @father.children.each do |child|
    puts @father.object_id == child.parent.object_id
  end

我原以为这里的结果都是true

相反,他们都是false

为什么ActiveRecord以这种方式工作而不是认识到这些是相同的Ruby对象?

ruby-on-rails ruby
5个回答
2
投票

要在可能的情况下返回现有对象而不是创建新对象,ActiveRecord必须跟踪创建了哪些对象以及它们响应的数据库中的哪个条目,这将是一些开销。即便如此,它仍然需要在数据库中查找child.parent才能知道它与@father代表的条目相同,因此从这个缓存中没有任何可观的增益性能(在红宝石方面,它保证分配多个对象但是以记账开销为代价,但在数据库方面它应该基本相同)。

因此,鉴于AR人员可能决定防止对应于相同数据库条目的不同对象将是有害的或者至少不值得努力,所以他们选择不这样做。


2
投票

对于那些在被问到这些年后偶然发现的人(像我一样!),请查看https://stackoverflow.com/a/4116397/1000655

它建议使用:inverse_of建立双向关联。我希望我过去没多次浏览过那么多文档!


1
投票

对象ID是对象的指针(种类)。 rails对象的加载不会“共享”内存空间,因此当您执行child.parent时,您将获得父对象的副本。要理解这一点 - 你可以做parent.something = foo,然后比较child.parent.something,你会发现它们是不同的。您必须从数据库重新加载子项,然后才能将更改反映到父对象。

但是,您使用错误的ID值的可能性很大。如果需要ActiveRecord ID(例如SQL DBMS中ID列的值),请使用@ father.id == child.parent.id


1
投票

重用对象是有问题的。如果对模型实例进行更改,但在保存之前,还会执行另一个带回同一对象的查找,该怎么办?新的应该反映数据库,但旧的应该仍然有更改的数据。

所以,是的,跟踪每个实例和每个实例中的脏字段将是一个很大的开销。节省的内存不值得付出努力。


0
投票

就我而言,AR至少应该支持身份地图插件。这是我处理AR时遇到的最大问题。我意识到它增加了一些开销,但是短暂的内存开销比通过一次又一次地拉出相同的记录而对数据库的过度税收更好。就像GC一样。您可以自己完成,也可以使用高级语言将其抽象出来,以便您可以专注于业务逻辑。您可以真正大惊小怪优化您的AR,或者您可以利用身份地图。

© www.soinside.com 2019 - 2024. All rights reserved.