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

Transform parent class instance into a child one #667

Open
davidsavoie1 opened this issue Mar 29, 2018 · 7 comments
Open

Transform parent class instance into a child one #667

davidsavoie1 opened this issue Mar 29, 2018 · 7 comments

Comments

@davidsavoie1
Copy link

Hi!

If I create an instance of a Parent class, how can I make a copy of it then save it as a Child class instance that inherits from Parent? Do I only change the type property?

Thanks!

@davidsavoie1
Copy link
Author

Well, it seems that only changing the type property won't cut it! I've tried with this and it seems to be working...

const child = new Child(parent.copy().raw());

Is there a better way you can think of that I'm missing here?

Many thanks again for your awesome library!

@davidsavoie1
Copy link
Author

Here's another thing I noticed... If I use a publication to restrict some of the fields of the Child class, as in this example:

Meteor.publish('Child.all.descriptions', function () {
  return Child.find({}, { fields: { code: 1, desc: 1, client: 1, state: 1 } });
});

If I don't include the type field in the fields selector, the data doesn't seem to get to the client, as if Astronomy didn't have enough information to figure out which class I'm asking for. If I do publish without fields selector then no problem. Is it expected behavior?

Do I only have to include the type field and be done with it?

@lukejagodzinski
Copy link
Member

const child = new Child(parent.raw());

should be just enough to create a child that has set all its fields set to values from the parent.

If it goes about publication, I should probably fix that to automatically publish the type field even if a user does not provide it.

@davidsavoie1
Copy link
Author

OK thanks! I just stumbled on yet another bug I've had a hard time to find that was due to this type field problem... I didn't remember I solved it already somewhere else! 😜

As for the child/parent issue, I guess I don't need to copy the parent first, since using new child will create a copy itself! Makes sense!

Thanks again!

@Genroa
Copy link

Genroa commented Apr 10, 2018

I agree that child class objects should be allocated wih the right class, even if they are queried from the parent class' find method. Because of this, overriding methods/defining new properties has no use because after saving, if you findOne again, it will be cast to a Parent instance.

@red-meadow
Copy link

red-meadow commented Apr 26, 2018

Hello!

I have a slightly different question: what is a proper way to transform a document from one child class to another (not create a copy)? I tried the solution mentioned above but the problem is that I don't change the fields of the existing document but instead remove it and create another one with the same id. Please, take a look at the code:

const Area = Class.create({
  name: 'Area',
  collection: new Mongo.Collection('areas'),
  typeField: 'type',
  fields: {
    size: Number
  }
})

const Forest = Area.inherit({
  name: 'Forest',
  fields: {
    plants: [String]
  }
})

const Wasteland = Area.inherit({
  name: 'Wasteland',
  fields: {
    pollution: Number
  }
})
// server.js
// create an instance of the first child class
let newForest = new Forest()
newForest.size = 500
newForest.plants = ["Oak"]
newForest.save()  // {_id: "6rrTAkieFmgjwv62T", type: "Forest", size: 500, plants: Array(1)}

// transform it to the the second child class
let forest = Forest.findOne()
let wasteland = new Wasteland(forest.raw())
wasteland.pollution = 700
forest.remove()    // to avoid duplicate key error
wasteland.save()  // {_id: "6rrTAkieFmgjwv62T", type: "Wasteland", size: 500, pollution: 700}

The final document is just what I need but remove and insert operations fire the related events which are not desired in this case.

Is there a better way to do it? Is switching classes with Astronomy a right way of thinking at all?
Than you in advance!

@lukejagodzinski
Copy link
Member

lukejagodzinski commented Apr 27, 2018

@red-meadow

Is switching classes with Astronomy a right way of thinking at all?

Everything depends on your use case. Don't know why you're doing it but if your use case requires that and it's not doable in another way that's ok.

The final document is just what I need but remove and insert operations fire the related events which are not desired in this case.

Using Astronomy requires triggering all the events that you've created. If you don't need to validate a document, you could just use plain collections. There is also another way of doing it but not perfect:

const forest = Forest.findOne();
const wasteland = new Wasteland(forest.raw());
wasteland.pollution = 700;
try {
  wasteland.validate();
  // Use Mongo collection directly to update document.
  Wasteland.getCollection().update(wasteland._id, { $set: wasteland.raw() });
} catch (err) {
  // Do something with validation error.
}

Haven't tested it but should work.

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

4 participants