1 2 3 4 5
if @foo.update_attributes(params[:foo]) and @foo.bar.update_attributes(params[:bar]) redirect_to foo_url(@parent) else render :action => "edit" end
Refactorings
No refactoring yet !
Fabien Jakimowicz
July 29, 2008, July 29, 2008 22:21, permalink
there is a lot of way to clean this, but without any other information (relation type between @foo and bar, form, ...) i can just propose something using exceptions and transactions.
A transaction will roll back any modifications if there is any failure. In your case, you need to save both instances only if both of them are valid. If one fail, the entire transaction will fail and nothing will be saved
1 2 3 4 5 6 7
def update_foo_and_bar # You can also use @foo.class.transaction and @foo.bar.class.transaction if you have multiple database at the same time ActiveRecord::Base.transaction {@foo.update_attributes!(params[:foo]) and @foo.bar.update_attributes!(params[:bar])} redirect_to foo_url(@parent) rescue ActiveRecord::RecordNotSaved render :action => 'edit' end
Adam
August 11, 2008, August 11, 2008 18:06, permalink
Set accessible => true in your model and use a nested fields_for block.
app/models/foo.rb
1 2 3
class Foo < ActiveRecord::Base has_one :bar, :accessible => true end
app/controllers/foos_controller.rb
1 2 3 4 5 6 7 8 9
def update @foo = Foo.find(params[:id]) if @foo.update_attributes(params[:foo]) redirect_to foo_url(@parent) else render :action => "edit" end end
app/views/foos/edit.html.erb
1 2 3 4 5 6 7 8 9
<% form_for @foo do |f| %> <%= f.text_field :name %> <% f.fields_for :bar, @foo.bar do |b| %> <%= b.text_field :name %> <% end %> <%= submit_tag "Submit" %> <% end %>
What's the best way to save multiple models in one action. Generally this is a case where you use form_for to update a model and fields_for to edit an associated model as well. The trick is to not save one of the models if the other has errors, and to generally handle all of the errors properly. This is how I have done it, but it seems simple, and in some cases there are more than just two models to deal with and I don't want to just keep using more and expressions.