pouchdb-community / ember-pouch

PouchDB/CouchDB adapter for Ember Data
Apache License 2.0
281 stars 76 forks source link

How to retrieve an attachment's data blob? #115

Open mattmarcum opened 8 years ago

mattmarcum commented 8 years ago

It looks like I got attachments saving correctly using an attachment transform. However, when I pull the record back out stub is set to true and data is undefined when I look at the data in my deserializer.

Is there any way to get relational pouch to automatically retrieve attachments? I.e. pass {attachments:true} like you can with regular pouch?

mattmarcum commented 8 years ago

ok, finally got some time to work on this again... I couldn't figure out a way to pass an option to relational-pouch to have it retrieve the attachment when it retrieves the record on the first pass so I created a mixin that just invokes the db.rel.getAttachment off of the adapter, it looks something like this...

export default Model.extend({
  attachments: attr('attachment'),

  retrieveAttachement(name) {
    let constructor = this.constructor;
    let adapter = this.store.adapterFor(constructor.modelName);

    return adapter.db.rel.getAttachment(adapter.getRecordTypeName(this.constructor), this.get('id'), name)
      .then(data => {
        this.get('attachments').findBy('name', name).setProperties({
          data,
          stub: false
        });
        return data;
      });
  },

  retrieveAttachments: Ember.on('didLoad', function() {
    let attachments = this.get('attachments');

    if (Ember.isNone(attachments)){ return; }

    attachments.forEach(attachment => {
      this.retrieveAttachement(attachment.name);
    });
  })

If you don't want the attachments to autoload then you can leave off the retrieveAttachments function or just change it to a regular method. The attachment transform is the one that was up here for a pr a while ago...

export default DS.Transform.extend({
  deserialize: function(serialized) {
    if (isNone(serialized)) { return null; }

    return keys(serialized).map(function (attachmentName) {
      return Ember.Object.create({
        name: attachmentName,
        content_type: serialized[attachmentName]['content_type'],
        data: serialized[attachmentName]['data'],
        stub: serialized[attachmentName]['stub'],
      });
    });
  },

  serialize: function(deserialized) {
    if (!Ember.isArray(deserialized)) { return null; }

    return deserialized.reduce(function (acc, attachment) {
      const serialized = {
        content_type: attachment.get('content_type'),
      };
      if (attachment.get('stub')) {
        serialized.stub = true;
      } else {
        serialized.data = attachment.get('data');
      }
      acc[attachment.get('name')] = serialized;
      return acc;
    }, {});
  }
});

I can create a PR for all this if anyone wants it...although I'm not too sure how to write tests for this stuff.

nolanlawson commented 8 years ago

I think such a PR is very much desired, although I admit I don't really know much about the test setup either. (Despite my name being on this project, it's mostly been managed by others, and my own Ember knowledge has been lacking recently.)

If you need help, though, I've found the #ember channel on IRC Freenode or the Ember Slack channel always has folks who are willing to help advise. :)

backspace commented 8 years ago

I have some acceptance tests that work with attachments. I think you could use something like that in combination with techniques like in the adapter tests.