Почему ActiveRecord не настолько умен, чтобы знать, что object_id отца должен быть равен object_id родителя его потомков? - PullRequest
4 голосов
/ 20 августа 2009
  @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?

Ответы [ 5 ]

2 голосов
/ 13 августа 2013

Для тех, кто спотыкается через эти годы после того, как его спросили (как я!), Проверьте https://stackoverflow.com/a/4116397/1000655.

Предлагается использовать :inverse_of для настройки двунаправленных ассоциаций. Хотелось бы, чтобы в прошлом я не просматривал эту часть документации столько раз!

2 голосов
/ 20 августа 2009

Чтобы вернуть существующие объекты, когда это возможно, вместо создания новых, ActiveRecord должен был бы отслеживать, какие объекты были созданы и на какую запись в базе данных они отвечают, что может быть связано с дополнительными затратами. Даже тогда ему все равно пришлось бы искать child.parent в базе данных, чтобы знать, что это та же самая запись, которую представляет @father, так что не было бы никакого существенного выигрыша в производительности от этого кеширования (хорошо, на стороне ruby ​​он экономит, выделяя несколько объекты, но за счет затрат на бухгалтерию, но на стороне базы данных это должно быть в основном то же самое).

Таким образом, учитывая, что сотрудники AR, вероятно, решили, что предотвращение различных объектов, соответствующих одной и той же записи в базе данных, будет либо вредным, либо, по крайней мере, не стоит затраченных усилий, поэтому они решили не делать этого.

1 голос
/ 20 августа 2009

Повторное использование объектов проблематично. Что делать, если вы вносите изменения в экземпляр модели, но перед тем, как сохранить его, вы делаете другое обнаружение, которое возвращает тот же объект? Новый должен отражать базу данных, но старый должен по-прежнему иметь измененные данные.

Так что да, было бы очень сложно отслеживать каждый экземпляр и грязные поля в каждом. Экономия памяти не будет стоить усилий.

1 голос
/ 20 августа 2009

Идентификатор объекта - указатель (своего рода) на объект. Загрузка объектов rails не «разделяет» пространство памяти, поэтому вы получаете копию родительского объекта, когда выполняете child.parent. Чтобы понять это - вы можете сделать parent.something = foo, а затем сравнить child.parent.something, и вы увидите, что они разные. Вам придется перезагрузить дочерний объект из базы данных, прежде чем он отразит изменения в родительском объекте.

Однако, скорее всего, вы используете неправильное значение идентификатора. Если вам нужен идентификатор ActiveRecord (например, значение столбца ID в вашей СУБД SQL), используйте @ Father.id == child.parent.id

0 голосов
/ 04 февраля 2011

Насколько мне известно, AR должен по крайней мере поддерживать плагин Identity Map. Это самая большая проблема, с которой я сталкиваюсь при работе с AR. Я понимаю, что это добавляет некоторые накладные расходы, но непродолжительные накладные расходы памяти лучше, чем неоправданный налог на базу данных, поскольку она снова и снова проверяет одни и те же записи. Это как GC. Вы можете сделать это самостоятельно или использовать язык высокого уровня, чтобы абстрагировать его, чтобы вы могли сосредоточиться на бизнес-логике. Вы можете действительно суетиться, чтобы оптимизировать свой AR, или вы можете воспользоваться Identity Map.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...