Reputation: 326
I want to preview what the model will look like when saved without currently saving to the database.
I am using @event.attributes =
because that assigns but does not save attributes for @event
to the database.
However, when I also try to assign the audiences
association, Rails inserts new records into the audiences_events
join table. Not cool. Is there a way to preview what these new associations will look like without inserting into the join table?
class Event < ActiveRecord::Base
has_and_belongs_to_many :audiences # And vice versa for the Audience model.
end
class EventsController < ApplicationController
def preview
@event = Event.find(params[:id])
@event.attributes = event_params
end
private
def event_params
params[:event].permit(:name, :start_time, :audiences => [:id, :name]
end
end
Possible solutions that I thought of, but don't know how to do:
Any help with these would be great!
UPDATE:
After the reading the great answers below, I ended up writing this service class that assigns the non-nested attributes to the Event model, then calls collection.build on each of the nested params. I made a little gist. Happy to receive comments/suggestions.
https://gist.github.com/jameskerr/69cedb2f30c95342f64a
Upvotes: 7
Views: 5771
Reputation: 9
I know that this is a pretty old question, but I found a solution that works perfectly for me and hope it could save time to someone else:
class A
has_many :bs, class_name 'B'
end
class B
belongs_to :a, class_name: 'A'
end
a.bs.target.clear
new_bs.each {|new_b| a.bs.build new_b.attributes.except('created_at', 'updated_at', 'id') }
you will avoid autosave that Rails does when you do a.bs = new_bs
Upvotes: 0
Reputation: 101976
Creating transactions is pretty straight forward:
Event.transaction do
@event.audiences.create!
@event.audiences.first.destroy!
end
Or
@event.transaction do
@event.audiences.create!
@event.audiences.first.destroy!
end
Notice the use of the "bang" methods create!
and destroy!
, unlike create
which returns false create!
will raise an exception if it fails and cause the transaction to rollback.
You can also manually trigger a rollback anywhere in the a transaction by raising ActiveRecord::Rollback
.
build
instantiates a new related object without saving.
event = Event.new(name: 'Party').audiences.build(name: 'Party People')
event.save # saves both event and audiences
Upvotes: 4
Reputation: 163
In these docs you have:
When are Objects Saved?
When you assign an object to a has_and_belongs_to_many association, that object is automatically saved (in order to update the join table). If you assign multiple objects in one statement, then they are all saved.
If you want to assign an object to a has_and_belongs_to_many association without saving the object, use the
collection.build
method.
Here is a good answer for Rails 3 that goes over some of the same issues
Upvotes: 7