vsivsi / meteor-file-collection

Extends Meteor Collections to handle file data using MongoDB gridFS.
http://atmospherejs.com/vsivsi/file-collection
Other
159 stars 37 forks source link

How to store a file ID relationship in a separate MongoDB document? #120

Open brylie opened 8 years ago

brylie commented 8 years ago

User Story

As a developer I would like to create a relationship between a FileCollection document and a document stored in a separate collection so that I can display, or link to, the file when displaying the related document

Support/documentation request

We would like to create a relationship between a FileCollection document and a document in a separate collection. For example, a user avatar could be uploaded to a FileCollection and the resulting ID would be added to the user profile document. Then, the avatar could be displayed on the user profile page.

We cannot figure out how to create the relationship from within the FileCollection.on() callback, since that seems to be defined in a global context. How can we associate a FileCollection document with a document in a separate collection?

brylie commented 8 years ago

For clarification, when we try to initialize the FileCollection.resumable.on('fileAdded') callback from within a Template..onRendered() callback, we get unexpected results. We are trying to access the template data context from within the resumable.on() callback, so that we can create a relationship between the file document and a document in a separate collection.

What would be a better approach to creating relationship(s) between FileCollection files and other documents in separate collection(s)?

vsivsi commented 8 years ago

I would do this on the server-side. You can .observe() the file-collection there for changes, including such things as the successful completion of an upload. Here is some example code that does just that (in this case creating a thumbnail image and connecting it with the original).

https://github.com/vsivsi/meteor-file-job-sample-app/blob/master/sample.coffee#L522-L534

brylie commented 8 years ago

Thanks. How would we pass the related entity ID to the observe function? E.g. a profile ID related to a profile image file.

vsivsi commented 8 years ago

Using metadata included when you initially insert the empty file on the client. Or in the allow rule that validates that insert (which would need to check that the metadata corresponds to the authenticated user anyway).

vsivsi commented 8 years ago

Another alternative would be to write a Meteor method that inserts the empty file document on server with the relevant metadata. Many prefer writing explicit methods to allow/deny rules.

brylie commented 8 years ago

For clarification, we are using the FileCollection.resumable, which is initialized in Meteor.startup, so we only call insert from within the resumable.on('fileAdded', ...).

We are actually trying to associate a text file with another collection document, and I just provided the user profile photo as a quick example. Imagine a situation where someone wants to attach a product image to a product, or something similar.

brylie commented 8 years ago

An ideal situation would be something like the following:

  1. we create a template instance variable referencing a resumable instance
  2. the resumable instance is initialized with a FileCollection reference, as well as a fileAdded callback function
  3. from within the fileAdded callback function, we upload the file as well as add a reference to the subsequent file ID to a related document in a separate collection
vsivsi commented 8 years ago

This boils down to a pretty general programming/database question.

Ignore the fact that file data is being uploaded. You are adding a document to a collection based on an event (that just happens to represent a requested file upload), and you want that document to point to some other pre-existing document in a different collection (and/or vice versa). How would you do that? There are many possible ways, and the right answer for you depends on your app's requirements and how it is designed. I don't know those things about your app, and this is not really a file-collection issue, so my ability to help you further is pretty limited.

If you don't know how to use them, you should look into Meteor methods. You could write a server-side method that is invoked from within the fileAdded callback. On the server, given parameters containing the necessary information to make the connection (e.g. file id, other doc id), the method can validate the request (permissions, consistency, etc), insert the file-collection file doc, along with any metadata needed to link it to the other document. Then, if desired, it can also update the other document to link back to the file-collection file (using the file id or other metadata). When the method calls back on the client, then the upload can proceed. That's one "Meteor" way, but there are other patterns, such as doing the same actions on the client and writing allow/deny rules to validate on the back end.

Anyway, I hope that helps. But please appreciate that it is tough to help someone design their app remotely via github issue. And unless there is a suspected bug somewhere in my package, doing so is not really the best use of the limited time I have available for open source work. If you have further questions specifically about using resumable.js, you should consult its documentation and GitHub issues. It is a separate project, and I can't really support it beyond the server-side integration that file-collection provides.

brylie commented 8 years ago

I understand the basic idea/pattern here, and we were able to solve it using a Session variable.

The main challenge was that the FileCollection.resumable needed to be defined in Meteor.startup, as the documentation demonstrates. We would prefer to be able to use a resumable instance in a template level scope, such as in Template..onCreated, since resumable can be binded to a template DOM object..

vsivsi commented 8 years ago

I see. You can create as many resumable instances as your app requires. You don't need to use the built-in instance provided when you set the resumable: true option on file-collection. However, if you want to use resumable at all, you do still need to set that option on the server, because it sets up the backend as well as the client instance. If you set up you own resumable instance(s), you will have the flexibility to do that in whatever scope you want. You do need to setup the resumable instance(s) to be compatible with the back end support: https://github.com/vsivsi/meteor-file-collection/blob/master/src/resumable_client.coffee#L28-L46

See these issues for more discussion of using custom/multiple resumable instances: https://github.com/vsivsi/meteor-file-collection/issues/71 https://github.com/vsivsi/meteor-file-collection/issues/102