Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Pushing a discriminated object in a non-discriminated array will strip its special properties #2399

Closed
anoirclere opened this issue Oct 21, 2014 · 3 comments
Milestone

Comments

@anoirclere
Copy link

Hello,
I ran against this issue today.

I have these models :

var mongoose = require('mongoose'),
    Schema = mongoose.Schema;

var ThingContainerSchema = Schema({
  title: String,
  things: [{type: Schema.Types.ObjectId, ref: 'Thing'}]
});

module.exports = mongoose.model('ThingContainer', ThingContainerSchema);
var mongoose = require('mongoose'),
    Schema = mongoose.Schema,
    util = require('util');

// from https://github.com/LearnBoost/mongoose/pull/1647
function AbstractThingSchema() {
  Schema.apply(this, arguments);

  this.add({
    name: String,
  });
}
util.inherits(AbstractThingSchema, Schema);
module.exports = AbstractThingSchema;
var mongoose = require('mongoose'),
    AbstractThingSchema = require('./abstract_thing'),
    ThingSchema = new AbstractThingSchema();

module.exports = mongoose.model('Thing', ThingSchema);
var mongoose = require('mongoose'),
    Schema = mongoose.Schema,
    Thing = require('./thing'),
    AbstractThingSchema = require('./abstract_thing');

var SpecialThingSchema = new AbstractThingSchema({
  specialAttribute: String
});

module.exports = Thing.discriminator('SpecialThing', SpecialThingSchema);

Now, I have a ThingContainer and I want to add a SpecialThing to its array of Things. The issue is that the push method will cast the SpecialThing object and strip its "specialAttribute" as well as Mongoose's discriminating attribute "__t".

console.log(myThingContainer.things);
// [{_id: 544624d65a6efba21b558db3, name: "Thing 1"}, {_id: 544624d65a6efba21b558db4, name: "Thing 2"}]

var special = new SpecialThing({
  name: "Special Thing",
  specialAttribute: "Very Special"
});

console.log(special);
// {_id: 544625c8044511cd1bbfb28d, name: "Special Thing", __t: 'SpecialThing', specialAttribute: "Very Special"}


myThingContainer.things.push(special);
console.log(myThingContainer.things);
// [{_id: 544624d65a6efba21b558db3, name: "Thing 1"}, {_id: 544624d65a6efba21b558db4, name: "Thing 2"}, {_id: 544625c8044511cd1bbfb28d, name: "Special Thing"}]

My current workaround is to avoid the push method :

myThingContainer.things = myThingContainer.things.concat([special]);
console.log(myThingContainer.things);
// [{_id: 544624d65a6efba21b558db3, name: "Thing 1"}, {_id: 544624d65a6efba21b558db4, name: "Thing 2"}, {_id: 544625c8044511cd1bbfb28d, name: "Special Thing", __t: 'SpecialThing', specialAttribute: "Very Special"}]

I wonder if the push method should be aware of discriminated objects attributes ?

@vkarpov15 vkarpov15 added this to the 3.8.19 milestone Oct 28, 2014
@vkarpov15
Copy link
Collaborator

Interesting. I'll take a look at this when I can.

@vkarpov15 vkarpov15 modified the milestones: 3.8.20, 3.8.19 Nov 9, 2014
@alabid
Copy link
Contributor

alabid commented Nov 10, 2014

@anoirclere myThingContainer.things already seems to have been populated. Can you provide a link to the entire project where you found this bug or just post some more code illustrating the bug? That'd be very helpful.

@anoirclere
Copy link
Author

@alabid Yes in my case myThingContainer.things is populated. Do you mean push() is not supposed to work with populated arrays? Here's my code. A Building is a specialized Group, and a Residence contains an array of Group objects.

/*
 * Add building
 */
router.post('/', function(req, res, next) {
  var building = new Building({
    name: req.body.newBuildingName,
    type: req.body.newBuildingType,
    residence: req.residence._id,
  });

  building.save(function (err, building) {
    if(err) return next(err);

    //req.residence.groups.push(building);
    // The commented line above doesn't work since Mongoose will strip property '__t' from Building object at push.
    // Workaround : don't use rewritten "push" method.
    req.residence.groups = req.residence.groups.concat([building]);

    req.residence.groups.sort(function(a, b) {
      return (a.name < b.name) ? -1 : 1;
    });

    req.residence.save(function (err, residence) {
      if(err) return next(err);
      res.render('shared/_edit_buildings');
    });
  });
});

alabid added a commit to alabid/mongoose that referenced this issue Nov 19, 2014
alabid added a commit to alabid/mongoose that referenced this issue Nov 19, 2014
alabid added a commit to alabid/mongoose that referenced this issue Nov 19, 2014
vkarpov15 added a commit that referenced this issue Dec 5, 2014
gh-2399 prevent casting for discriminator models when pushing to array
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants