Вызов ActiveReecord #relationship_ids = [1,2,3] сохраняет немедленно. Есть обходные пути? - PullRequest
3 голосов
/ 12 февраля 2010

Я обнаружил странность в методе Activereecord #relationship_ids (который добавляется автоматически, когда вы объявляете 'has_many'), который сразу сохраняет для существующих записей, что вызывает у меня некоторые проблемы, и мне интересно, есть ли у кого-нибудь полезные советы .

Я использую Rails 2.3.5.

Рассмотрим этот простой сценарий, где в статье есть теги has_many, скажем:

a = Article.first
a.name = "New Name" # No save yet
a.author_id = 1     # No save yet
a.tag_ids = [1,2,3] # These changes are saved to the database
                    # immediately, even if I don't subsequently
                    # call 'a.save'

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

(Возможно, уместно то, что если «а» - это новая статья, а не существующая, все ведет себя так, как я ожидал - ничего не сохраняется, пока я не вызову «a.save»)

У меня довольно неприятный обходной путь - я могу переопределить метод tag_ids = в моей модели, чтобы вместо этого заполнить переменную экземпляра и фактически сохранить связанные модели в обратном вызове before_save.

Но я бы хотел знать, как проще сделать это для каждой модели с отношением has_many, для которого я хотел бы создать средство предварительного просмотра.

У кого-нибудь есть какие-либо исправления / обходные пути / общие советы? Спасибо!

1 Ответ

3 голосов
/ 12 февраля 2010

Есть причина, по которой все так. Это называется внешние ключи. В отношении a имеет много связей, информация, которая ссылается на модель, которая имеет много, хранится вне этой модели как внешний ключ.

Как и в статьях, имеет много тегов. Информация, которая связывает тег со статьей, хранится либо в таблице тегов, либо в таблице соединений. Когда вы вызываете функцию сохранения для статьи, вы сохраняете только статью.

Активная запись изменяет эти другие записи немедленно. За исключением случая, когда вы работаете с новой статьей, которая еще не была сохранена. Rails откладывает создание / обновление связанных записей, если не знает, какой идентификатор поместить во внешний ключ.

Однако, если вы изменяете существующие записи, решение, которое вы выбрали, - это действительно все, что вы можете сделать. Есть еще более уродливый хак, использующий accepts_nested_attributes_for, но это действительно не стоит усилий.

Если вы хотите добавить это поведение ко многим моделям, но не ко всем моделям, возможно, вы захотите написать простой плагин для переопределения назначения нужного вам метода и добавления обратного вызова в вызове метода одного класса. Взгляните на источник чего-то вроде acts_as_audited, чтобы увидеть, как это делается.

Если вы хотите добавить это поведение ко всем моделям, вы можете написать обертку для has_many, чтобы сделать это.

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