rmachielse / ember-data-paperclip

Ember Data Paperclip
https://rmachielse.github.com/ember-data-paperclip
MIT License
7 stars 2 forks source link

Ember Data Paperclip

Build Status Ember Observer Score

This addon provides an ember file attribute to use with rails paperclip. A demo can be found here.

Installation

Install the addon with the following command:

ember install ember-data-paperclip

After installation, you can optionally add the serializer-mixin to your serializer. You only need this if you want to use model properties in your file path (see configuration point 4).

// app/serializers/application.js

import ActiveModelSerializer from 'active-model-serializer';
import SerializerMixin from 'ember-data-paperclip/mixins/serializer-mixin';

export default ActiveModelSerializer.extend(SerializerMixin);

Configuration

This addon needs some configuration before you can use it. Add the following to your config/environment.js:

// config/environment.js

  ...

  paperclip: {
    path: ':class/:attachment/:id_partition/:style/:filename.jpg'
  },

  ...

The variables that are used above are available by default. If you need other variables or want to override the default ones, there are three ways to do that:

  1. Directly in your config file. For example, if your path begins with :base, you can add base like this:

     // config/environment.js
    
       ...
    
       paperclip: {
         path: ':base/:class/:attachment/:id_partition/:style/:filename.jpg',
         base: 'https://files.example.com'
       },
    
       ...
  2. By adding options on the attribute. For example if the filename is always 'data':

     // app/models/product.js
    
     import Model from 'ember-data/model';
     import attr from 'ember-data/attr';
    
     export default Model.extend({
       photo: attr('file', {
         filename: 'data'
       })
     });
  3. By sending it from the backend. For example with rails active model serializers:

     # app/serializers/product_serializer.rb
    
     class ProductSerializer < ActiveModel::Serializer
       attributes :id, :photo
    
       def photo
         if object.photo.present?
           {
             filename: object.photo_file_name
           }
         end
       end
     end
  4. By providing them on your model. For example if you want to override id_partition:

     // app/models/product.js
    
     import Model from 'ember-data/model';
     import attr from 'ember-data/attr';
     import Ember from 'ember';
    
     const { computed } = Ember;
    
     export default Model.extend({
       photo: attr('file'),
    
       id_partition: computed('id', function() {
         return this.get('id');
       })
     });

    Please note that this requires the SerializerMixin to be included in your serializer.

Usage

In your model add a file attribute:

// app/models/product.js

import Model from 'ember-data/model';
import attr from 'ember-data/attr';

export default Model.extend({
  photo: attr('file')
});

Getting

You can generate urls for different styles like this:

var url = product.get('photo').url();
// products/photos/000/000/001/original/data.jpg

var thumbnailUrl = product.get('photo').url('thumbnail');
// products/photos/000/000/001/thumbnail/data.jpg

You can retrieve the object URL of the file like this:

product.get('photo').objectURL('thumbnail').then((thumbnailObjectURL) => {
  console.log(thumbnailObjectURL);
});

You can also retrieve the base64 data URL of the file:

product.get('photo').dataURL('thumbnail').then((thumbnailDataURL) => {
  window.open(thumbnailDataURL);
});

Utilities to use these urls like computed properties are available as well:

import Model from 'ember-data/model';
import attr from 'ember-data/attr';
import fileURL from 'ember-data-paperclip/utils/file-url';
import dataURL from 'ember-data-paperclip/utils/data-url';
import objectURL from 'ember-data-paperclip/utils/object-url';

export Model.extend({
  photo: attr('file'),

  photoThumbnailURL: fileURL('photo', 'thumbnail'),

  photoThumbnailDataURL: dataURL('photo', 'thumbnail'),

  photoObjectURL: objectURL('photo')
});

A template helper is also available:

<img src={{file-url product.photo 'thumbnail'}} />

Setting

You can set the file from a file upload like this:

  ...

  change: function (e) {
    this.get('product.photo').update(e.target.files[0]);
  },

  ...

A file-upload component is also provided:

{{file-upload file=product.photo}}

When saving, this will cause the following request:

// POST /products/1

{
  "product": {
    "id": 1,
    "photo": "[base64data]"
  }
}

The photo will only be sent to your backend when it has changed. You can also remove the photo:

product.get('photo').clear();
product.save();

This will send the following to the backend:

// POST /products/1

{
  "product": {
    "id": 1,
    "photo": null
  }
}

Limitations

License

This project is released under the MIT License.