Search code examples
mongoidactivemodel

Only persist document if it has embedded documents with Mongoid?


I have a 2 level nested form (much like this) with the following classes. The problem I have is that when I don't add any intervals (the deepest embedded document) I don't want the second deepest document to be persisted either. In the owner I added a reject statement to check if there's any intervals being passed down, this works.

However, when the schedule originally had intervals but they where destroyed in the form (by passing _destroy: true) the schedule also needs to be destroyed. What would be the best way to do this? I would like to avoid a callback on the schedule that destroys the document after it is persisted.

class Owner
  include Mongoid::Document  
  embeds_many :schedules

  attr_accessible :schedules_attributes

  accepts_nested_attributes_for :schedules, allow_destroy: true, reject_if: :no_intervals?

  def no_intervals?(attributes)
    attributes['intervals_attributes'].nil?
  end      
end

class Schedule
  include Mongoid::Document
  embeds_many :intervals
  embedded_in :owner

  attr_accessible :days, :intervals_attributes

  accepts_nested_attributes_for :intervals,
                                allow_destroy: true,
                                reject_if: :all_blank
end

class Interval
  include Mongoid::Document
  embedded_in :schedule
end

Update: Maybe this is best done in the form itself? If all intervals is marked with _destroy: true, also mark the schedule with _destroy: true. But Ideally the solution would be client agnostic.


Solution

  • How about adding this to the Owner class:

    before_update do 
      schedules.each |schedule|
        schedule.destroy if schedule.intervals.empty?
      end
    end