Uploaded image for project: 'Mongoid'
  1. Mongoid
  2. MONGOID-1250

Destroying nested attributes behaves differently than ActiveRecord

    • Type: Icon: Task Task
    • Resolution: Done
    • 2.2.1
    • Affects Version/s: None
    • Component/s: None
    • Labels:

      I'm attempting to fire an after_destroy callback on an embedded association. The code will better explain the scenario:

      Here, in Mongoid, whether embedded or referenced, the callback will not fire.

      class Project
        include Mongoid::Document
        
        embeds_many :developers
        accepts_nested_attributes_for :developers, :allow_destroy => true
      
      end
      
      class Developer
        include Mongoid::Document
      
        belongs_to :project
        after_destroy :clbk
        
        private; def clbk; puts 'CLBK'; end
      
      end
      
      p = Project.create!
      p.developers.create!
      p.update_attributes! :developers_attributes => [ p.developers.first.attributes.merge({ :_destroy => '1' }) ]
      p.reload.developers.count #=> 0
      

      However, in a one-to-many ActiveRecord association, the callback will fire – because the associated object is considered to be destroyable (thus, it will actually destroy the object, not just the association). In Mongoid::Relations::Builders::NestedAttributes::Many#process:

        if destroyable?(attrs)
          existing.delete(doc)
        else
          ...
      

      Logically, it seems as though that line should read

      Unable to find source-code formatter for language: doc. Available languages are: actionscript, ada, applescript, bash, c, c#, c++, cpp, css, erlang, go, groovy, haskell, html, java, javascript, js, json, lua, none, nyan, objc, perl, php, python, r, rainbow, ruby, scala, sh, sql, swift, visualbasic, xml, yaml
      .destroy

      ... but adding that line causes a handful of specs to fail for nested_attributes.

      Mongoid::NestedAttributes##{name}_attributes= when the parent document is new when the relation is an embeds many when ids are passed when destroy attributes are passed when the ids match when allow_destroy is true when passed a 1 with destroy when the parent is persisted does not delete the removed document
           Failure/Error: address_one.should_not be_destroyed
             expected destroyed? to return false, got true
      

      All that being said, is there a reason it was designed this way? AND, what do you suggest for firing the callback without ugly controller code?

            Assignee:
            Unassigned Unassigned
            Reporter:
            FestivalBobcats FestivalBobcats [X]
            Votes:
            0 Vote for this issue
            Watchers:
            0 Start watching this issue

              Created:
              Updated:
              Resolved: