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

Associations allow assignment of objects of wrong type

      TLDR: We accidentally attached an existing mongoid object as an embedded object on another model. Removing this relationship with doc.embedded_doc = nil caused all "destroy" callbacks to be fired on the existing mongoid object.

      Here's a code sample

      # A top level document in the account collection
      class Account
        include Mongoid::Document
        has_many :projects, :dependent => :destroy
        after_destroy do
          puts "After destroy account fired"
      # A top level document in the project collection
      class Project
        include Mongoid::Document
        belongs_to :account
        after_destroy do
          puts "After destroy project fired"
      # A top level document in the invoice collection
      class Invoice
        include Mongoid::Document
        embeds_one :plan, :cascade_callbacks => true
      # An embedded document, that no collection exists for
      class Plan
        include Mongoid::Document
        embedded_in :invoice
      account = Account.create
      Project.create! account: account
      invoice = account.invoices.new
      # We shouldn't be allowed to set an Account to a Plan here, it's not a Plan class
      invoice.plan = a
      # Here the account will have its after_destory callbacks fired and the projects destroyed...
      invoice.plan = nil

      Adding a referenced document into an embedded relationship seems to work, regardless of the type of the document being added. Then when you go ahead and delete that relationship, it acts as if the document is being removed.

      Is this a known issue? I appreciate I asked mongoid to do something silly, but I would prefer it realized I was asking it to do something silly and threw an exception than mistakenly delete data. Is there an appetite for a fix for this, and if so what form should it take? I'm happy to look into submitting a PR, just want to know what, if any, would be an acceptable solution.

            Unassigned Unassigned
            snmaynard Simon Maynard
            0 Vote for this issue
            2 Start watching this issue