I would like to destroy a nested model if its attributes are blanked out in the form for the parent model - however, it appears that the ActiveRecord::Callbacks
are not called if the model is blank.
class Artist < ActiveRecord::Base using_access_control attr_accessible :bio, :name, :tour_dates_attributes has_many :tour_dates, :dependent => :destroy accepts_nested_attributes_for :tour_dates, :reject_if => lambda { |a| a[:when].blank? || a[:where].blank? }, :allow_destroy => true validates :bio, :name :presence => true def to_param name end end
and
class TourDate < ActiveRecord::Base validates :address, :when, :where, :artist_id, :presence => true attr_accessible :address, :artist_id, :when, :where belongs_to :artist before_save :destroy_if_blank private def destroy_if_blank logger.info "destroy_if_blank called" end end
I have a form for Artist which uses fields_for
to show the fields for the artist's associated tour dates, which works for editing and adding new tour dates, but if I merely blank out a tour date (to delete it), destroy_if_blank
is never called. Presumably the Artist controller's @artist.update_attributes(params[:artist])
line doesn't consider a blank entity worth updating.
Am I missing something? Is there a way around this?
I would keep the :reject_if block but insert :_destroy => 1 into the attributes hash if your conditions are met. (This is useful in the cases where it's not convenient to add _destroy to the form code.)
You have to do an extra check to see if the record exists in order to return the right value but the following seems to work in all cases for me.
accepts_nested_attributes_for :tour_dates, :reject_if => :reject_tour, :allow_destroy => true def reject_tour(attributes) exists = attributes['id'].present? empty = attributes.slice(:when, :where).values.all?(&:blank?) attributes.merge!({:_destroy => 1}) if exists and empty # destroy empty tour return (!exists and empty) # reject empty attributes end
You could apply when all attributes are blank by just changing the empty
calculation to:
empty = attributes.except(:id).values.all?(&:blank?)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With