06 Nov, 2007

Published at 05:33PM

Tagged with forms, programming, rails, and tips

This post has 0 comments

Updating multi-model forms in Rails

The other day I received an email about the post concerning multi-model forms in Rails. This person had a similar situation, but was having difficulty saving the records on an update. I didn’t make that part very clear, so I figured I’d complete the puzzle.

If you recall, there was a check in the set_model_attributes method that looks for an id (attributes[:id].blank?) so it’d know whether it was supposed to update or create. If there’s an id present, it must be an update.

Based on these two lines,

1
2
_model = send(model).detect {|m| m.id == attributes[:id].to_i}
_model.attributes = attributes

there’s a misconception that the model’s attributes are getting saved. Setting the attributes like this does not save them, but it’s easy to do. I’m using an after_update callback which looks like this:

1
2
3
4
5
6
7
8
9
10
class Course < ActiveRecord::Base

  has_many :holes, :dependent => :destroy
  has_many :tees,  :dependent => :destroy  

  after_update { |c| c.save_associated :holes, :tees }

  # ...

end

And the save_associated method looks like this:

1
2
3
4
5
6
7
8
9
10
def save_associated(*models)
  models.each do |model|
    send(model).each do |attributes|
      # handle validations before this point
      # and pass false to the save method to
      # ensure that the attributes get saved
      attributes.save(false)
    end
  end
end

If you’re only dealing with one association you can eliminate the parameters and the nested loop, as well as provide a more meaningful method name for the callback (such as save_holes). All in all, this seems to work pretty good.

Chris mentioned conductors in an earlier comment, which also seems like a viable option.

Comments

Do you have something to say about this post?
Protected by Defensio Textile Formatting Tips

or

Ryan Heath | Site Management A Ruby on Rails production.

This site is a Formed Function. Formed Function LLC | @formedfunction | Get in Touch