views:

44

answers:

1

I've got the following situation with ActiveRecord (in Rails 2.3.8):

class Order < ActiveRecord::Base
  has_many :documents
  accepts_nested_attributes_for :documents
end

class Document <ActiveRecord::Base
  belongs_to :order
end

Now, in a controller I want to direct the user differently depending on whether or not they made changes to existing records, e.g.

@order.attributes = params[:order]
if @order.changed?
  # save order
  # redirect one place
else
  # redirect another place
end

For that I want to use the changed? flag. It turns out that @order.changed? does not query the children.

I tried to implement that via an association proxy method on the has_many :documents association, like so:

  has_many :documents do
    def changed?
      any? {|doc| doc.changed?}
    end
  end

But this has the unintended side-effect that it loads the associated documents from disk, which apparently wipes out any changes that were made in the nested attributes assignment in @order.attributes = params[:order] This either seems an intentional design decision in Rails, but then how to solve it? Or is it a feature gap?

Thoughts?

Wolf

A: 

Hi,

you might have a look at the source of nested_records_changed_for_autosave.

It is not exactly what you want, but it has clues about how to do it. Especially association_instance_get which "Gets the specified association instance if it responds to :loaded?, nil otherwise."

hellvinz
Thanks for that bit of advice. That lead us down the right path of inquiry.It turned out that our actual issue was related to the fact that any in-memory objects created from nested attributes were overwritten in various validation rules and before_save hooks that inadvertently loaded the associations from disk, in particular :validates_presence_of :documents in the Order model will hose the use of nested attributes for updates.
Wolfram Arnold
no problem, glad to have helped.
hellvinz