This project is archived and is in readonly mode.

#3588 ✓resolved
Sai Emrys

:autosave => true + accepts_nested_attributes_for = circular validation & blown stack

Reported by Sai Emrys | December 16th, 2009 @ 09:51 PM

Consider the following:

class Discussion < ActiveRecord::Base
  belongs_to :context, :polymorphic => true
  has_many :messages, :dependent => :destroy, :inverse => :discussion
  accepts_nested_attributes_for :messages

class Message < ActiveRecord::Base
  belongs_to :discussion, :inverse => :messages, :autosave => true
  validates_presence_of :discussion

  def before_validation_on_create
    self.discussion ||=

Scenario 1:
Create a new message. Save the message. Discussion gets created pre-validation, the discussion gets validated and everything is saved properly. All is well, huzzah.

Scenario 2:
Create a new discussion together with nested message attributes. Save the discussion. It attempts to validate its messages, but they in turn try to validate their discussion, which tries to validate its messages... it recurses and blows stack. Boo.

This scenario can be prevented by turning off autosave => true, at the cost of breaking scenario 1.

This can also be prevented by turning off inverse (running from, at the cost of bug #2815 (#1943 may also be relevant), which makes Message's validation of its parent's existence fail. Additionally @discussion.messages.first.discussion != @discussion, which causes other issues. Fingertips' inverse_of patches nicely solve this.

I'm not sure how to fix this. Perhaps one could flag a record as having been validated at the BEGINNING of its validation cycle, and then not try to validate it again if that flag is set? This would prevent recursion, but might cause issues with mutually dependent validations of some sort that I'm failing to imagine.

Comments and changes to this ticket

Create your profile

Help contribute to this project by taking a few moments to create your personal profile. Create your profile »

<h2 style="font-size: 14px">Tickets have moved to Github</h2>

The new ticket tracker is available at <a href=""></a>

Referenced by