2009-12-13 2 views
5

Предположим, у нас есть стандарт Post & Комментировать модели с сообщением accepts_nested_attributes_for :commments и :autosave => true.Rails: Как я могу получить доступ к родительской модели вложенных ассоциаций новой записи?

Мы можем создать новый пост вместе с некоторыми новыми комментариями, например:

@post = Post.new :subject => 'foo' 
@post.comments.build :text => 'bar' 
@post.comments.first # returns the new comment 'bar' 
@post.comments.first.post # returns nil :(
@post.save # saves both post and comments simultaneously, in a transaction etc 
@post.comments.first # returns the comment 'bar' 
@post.comments.first.post # returns the post 'foo' 

Однако, мне нужно, чтобы иметь возможность различать изнутри комментарий (например, от его before_save или функции проверки) между

  1. этот комментарий не привязан к столбу (который является недействительным)
  2. этого комментарий прикреплен к неспасенным посту (который действует)

К сожалению, просто вызов self.post из комментария не работает, потому что в соответствии с ним он возвращает nil до тех пор, пока не произойдет сохранение. Разумеется, в обратном вызове я не (и не должен) иметь доступ к @post, только к самому себе из рассматриваемого комментария.

Итак: как я могу получить доступ к родительской модели вложенных ассоциаций новой записи, с точки зрения этой модели вложенной ассоциации?

(FWIW, фактический образец, с помощью которого я использую это, позволяет людям создавать голый «комментарий», а затем автоматически создаст «сообщение», чтобы его содержать, если его еще нет. Я упростил это например, поэтому это не относится к моему коду неуместными способами.)

ответ

5

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

Там есть билет с большим количеством обсуждения и без разрешения в багтрекере Rails об этом:

Nested attributes validations circular dependency

И предлагаемой резолюции:

nested models: build should directly assign the parent

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

Во втором билете, к которому я привязался, есть некоторые обходные пути.

+0

Как это сделать? Вы не хотите устанавливать столбец parent_id, поэтому вам придется добавить некоторые скрытые свойства для ребенка? – MattMcKnight

+0

Вы можете установить атрибут (например, родительский, дочерний) без установки необходимых _ids. Вот как это делает вложенную модель сбережения в настоящее время - у нее просто есть этот недостаток не быть рекурсивным. – Sai

+0

@Sai после опубликованных ссылок, я вижу, что это может быть достигнуто с помощью опции 'inverse_of'. – artificis

0

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