jagi / meteor-astronomy

Model layer for Meteor
https://atmospherejs.com/jagi/astronomy
MIT License
605 stars 66 forks source link

Observing an Astronomy Cursor #680

Closed yorrd closed 6 years ago

yorrd commented 6 years ago

I'm observing an astronomy cursor (created with AstronomyClass.find) with .observeChanges. In the resulting callbacks (for example added, the given objects don't contain transient fields or the helper methods.

Is this by design? How might I work around this? I don't really have a way to do this without observers due to the design of our framework

lukejagodzinski commented 6 years ago

Transient fields is not something that comes with the observeChanges method. Observe changes only return fields that were changed in the database and transient fields are not stored in db.

On Fri, Aug 3, 2018, 9:55 PM Yorrd notifications@github.com wrote:

I'm observing an astronomy cursor (created with AstronomyClass.find) with .observeChanges. In the resulting callbacks (for example added, the given objects don't contain transient fields or the helper methods.

Is this by design? How might I work around this? I don't really have a way to do this without observers due to the design of our framework

— You are receiving this because you are subscribed to this thread. Reply to this email directly, view it on GitHub https://github.com/jagi/meteor-astronomy/issues/680, or mute the thread https://github.com/notifications/unsubscribe-auth/ABAKXbOs6U6o4f-RAxj2m2uUsxIIfYoJks5uNKrBgaJpZM4VuiNl .

yorrd commented 6 years ago

Thanks for your reply!

What's your expert opinion on the best way to proceed? I could retrieve the actual class object when a added change event has occurred, but that seems like it might be less performant to me. Is it, or is it negligible?

lukejagodzinski commented 6 years ago

I don't know what you want to achieve. But if you're talking about transient fields, then you should probably not bother with them as their only temporary thing that gets computed depending on the other fields or other factors. It's definitely not something that you should care about when dealing with the update opreations

yorrd commented 6 years ago

Sorry, I'll explain :) I'm using the observeChanges function in the frontend to implement reactivity. So to speak, I'm "binding" a model to the UI with some custom logic. To achieve this, I'm updating a property on my UI class and forcing a render every time observeChanges gives me something. Because I'm directly putting the stuff I get from observeChanges into my data holder, there are no transient fields in there. Obviously, I would like to use them in the UI, though. Also, it would be helpful to be able to use helper functions in the UI.

Now to fix this, I could go ahead and not use the result I get from observeChanges but rather query the astronomy object to retrieve the actual astronomy class instance with transient fields and helper functions. That would mean more computational expense though in comparison to what I'm doing right now. This made me wonder why you decided not to pass the complete astronomy class instance in the observeChanges method.

I hope this was less confusing :)

lukejagodzinski commented 6 years ago

First of all, there is no way I could pass astronomy class instance to the observeChanges method. I'm not messing with Meteor cursors at all, so it's the original one.

Moreover, I think you don't understand how the observeChanges method works. It observe CHANGES in documents stored in collection and return those CHANGES and not entire DOCUMENTS. So that's one reason why I can't pass astronomy class instance (take a look at the method's description https://docs.meteor.com/api/collections.html#Mongo-Cursor-observeChanges)

If you want to get entire document, you should use the observe method instead. This method returns entire documents for each operation performed on the collection. However, those documents are still not astronomy class instances. However, you could make them so by doing something like this:

cursor.observe({
  changed(newDoc, oldDoc) {
    newDoc = new AstroClass(newDoc);
  }
});

However, you will still not get information about changes in the transient fields.

For what you want to achieve, there are reactive variables: ReactiveVar, ReactiveDict etc. It will detect all changes made in a document stored in these variables.

yorrd commented 6 years ago

First of all, there is no way I could pass astronomy class instance to the observeChanges method. I'm not messing with Meteor cursors at all, so it's the original one.

Ah, I get it. Thanks for the clarification!

I'm using the observeChanges method for the added event as well, which passes all fields as an argument, so that's working fine :)

Thanks for the suggestion, that's exactly what I did now.


Btw: I'm doing all this to create a generic rxjs subject which can bind to a database. One day when it's readable, I'll release the source. With your suggestions, it's quite elegant actually. You can basically say new MongoSubject(AstroClass, Cursor) and then subscribe to it. Because we're using rxjs to render our templates, that's amazing, because you can just pluck those into it directly and have a cursor be written to the screen reactively within one just line of code.

Thanks for your help! :+1: