Meteor collection2 type Object

244 views Asked by At

I'm trying to create a field modifiedBy with type: Object (to Meteor users).

I see you can setup blackbox: true for a Custom Object, but if I want to setup to a specific Object say a Group (collection) field modifiedBy is the logged in user, any pointers/help is greatly appreciated.

Thanks

1

There are 1 answers

8
halbgut On BEST ANSWER

As far as I see it, you have two options:

  • Store user-ids there with type: String
  • Denormalize it as you proposed

Denormalize it as you proposed

To denormalize it you can do something like this inside your schema:

...
modifiedBy: {
  type: object
}

'modifiedBy._id': {
  type: String,
  autoValue: function () {
    return Meteor.userId()
  }
}

'modifiedBy.username': {
  type: String,
  autoValue: function () {
    return Meteor.user().username
  }
}
...

As you pointed out, you'd want to update these properties when they change:

server-side

Meteor.users.find().observe({
  changed: function (newDoc) {
    var updateThese = SomeCollection.find({'modifiedBy.username': {$eq: newDoc._id}})
    updateThese.forEach () {
      SomeCollection.update(updateThis._id, {$set: {name: newDoc.profile.name}})
    }
  }
})

Store user-ids there with type: String

I'd recommend storing user-ids. It's cleaner but it doesn't perform as well as the other solution. Here's how you could do that:

...
modifiedBy: {
  type: String
}
...

You could also easily write a Custom Validator for this. Now retrieving the Users is a bit more complicated. You could use a transform function to get the user objects.

SomeCollection = new Mongo.Collection('SomeCollection', {
  transform: function (doc) {
    doc.modifiedBy = Meteor.users.findOne(doc.modifiedBy)
    return doc
  }
})

But there's a catch: "Transforms are not applied for the callbacks of observeChanges or to cursors returned from publish functions."

This means that to retrieve the doc reactively you'll have to write an abstraction:

getSome = (function getSomeClosure (query) {
  var allDep = new Tacker.Dependency
  var allChanged = allDep.changed.bind(allDep)
  SomeCollection.find(query).observe({
    added: allChanged,
    changed: allChanged,
    removed: allChanged
  })
  return function getSome () {
    allDep.depend()
    return SomeCollection.find(query).fetch()
  }
})