Forum: Ruby on Rails Creating/updating multiple associated objects at the same ti

Announcement (2017-05-07): is now read-only since I unfortunately do not have the time to support and maintain the forum any more. Please see and for other Rails- und Ruby-related community platforms.
Bce1d1b7c3ec7b577dcb42e254899e6b?d=identicon&s=25 Michael Schuerig (Guest)
on 2006-12-24 00:26
(Received via mailing list)
The problem: For me it's a common case that I want to create or update
multiple associated objects at the same time from a single params hash.

The restrictions: This is clearly functionality that belongs in the
model. The operation obviously has to be transactional, either all
objects are created/updated or none.

A solution. Well, it works for me.

  def initialize(attributes = nil)
    # initialize already executes inside a transaction
    # there's no point in adding a further transaction block
    base_attributes, child_attributes =

  # Use this instead of update_attributes in controller.
  def update_properties!(attributes)
    base_attributes, child_attributes =
    self.class.transaction do
      update_attributes(base_attributes) ||
        raise(ActiveRecord::RecordInvalid, self)

  def split_attributes(attributes)

  def attach_children(attributes)
    # find, create, or update the children based on given attributes
    # raises an exception if anything goes wrong

As I said, this works for me, but it doesn't feel nice and clean. I have
to override initialize, which I'd rather not do and leave this method
entirely to ActiveRecord. Similar for updating. Overriding
update_attributes suitably doesn't seem feasible[*], and I wouldn't
want to anyway.

[*] If anything goes wrong, the surrounding transaction has to be
aborted to cause a rollback. This can only be done *reliably* by
raising an exception from update_properties! as the method might be
executing in an outer transaction block in which case an exception has
to be raised out of that transaction block to actually abort the

As I'm pretty sure that I'm not the only one whose trying to tackle this
problem, I'm really interested in other approaches.


Michael Schuerig
This topic is locked and can not be replied to.