-
Notifications
You must be signed in to change notification settings - Fork 8
Attachment Library
Most applications need some way of:
- Storing and viewing files uploaded by users
- Associating these uploaded files with models (i.e. attaching them to models). For example, attaching an image or document to a post, setting a user profile picture etc.
We provide a full featured, flexible solution right out of the box!
-
ActsAsAttachmentOwnerServer-side DSL for declaratively configuring models to accept attachments -
attachment-libraryAngular directive for managing uploaded files on screen. This itself is made up of the following directives:-
attachment-browserFor browsing, editing and deleting uploaded files -
fine-uploaderFor uploading files to a backing store such as AWS S3, using the excellent (and recently open sourced!) FineUploader library -
url-referrerFor adding files to the library by directly supplying a URL
-
-
attachment-dropDirective to attach file(s) to a model, by dragging and dropping from the attachment library; or to detach file(s) from a model -
attachment-viewerDirective for viewing individual attachments. Depending on the type of attachment (video, image, document) an appropriate player or viewer is used. - The user can continue to use and navigate through the application while files are uploading
- AWS S3 storage support out of the box, with chunked and resumable uploading, and protected access via AWS's CloudFront CDN (can be easily extended to support different/additional backing stores and CDNs)
Of the above, you only really need to use the DSL, and the attachment-drop and attachment-viewer directives.
NOTE: We use JWPlayer, an HTML5 and Flash based video player for playing back video attachments. If you're not developing an open-source application, a license must be purchased. However, if you don't wish to do so, you can easily replace it with your own.
Lets say you want to be able to attach files to posts.
NOTE: Lets assume that you already have a Rails Post model, and an Angular view for editing posts (where you will let users attach files to the post being edited), and of course a controller powering this view.
We'll tackle the code required, by showing exactly how such a setup is already built into the starter kit.
We would like a post to accept a single 'main' image, and also accept zero or more files (images or anything else) as additional attachments.
We provide a convenient DSL for declaratively specifying just these types of scenarios and constraints, which is flexible enough to handle pretty much any scenario/constraint you can come up with. The DSL is defined in ActsAsAttachmentOwner, and the code is well documented.
ActsAsAttachmentOwner is written as an ActiveSupport::Concern, and any model that needs to be able to accept attachments must include this concern.
The Post model uses this DSL to specify the attachments it accepts, and with what constraints. Read together with the DSL documentation, is self-explanatory.
Now posts have been configured to accept attachments on the server side. Next, we need to construct the UI that let users attach files.
This is done simply by sprinkling some attachment-drop tags on the Angular view for editing posts. The attachment-drop directive enables users to attach file(s) to a model, by dragging and dropping from the attachment library; or to detach file(s) from a model.
attachment-drop needs to display the list of files currently attached, which means it needs this information to come from the server. Since the controller powering the Angular 'edit post' view gets the details of the post to be edited from the 'edit' action of the Rails PostsController, the corresponding Rails view that renders the post's JSON to the client is where this needs to happen. The details of the currently attached files need to be in a particular format, and we provide an easy way of ensuring this:
In this view, there are two fragments of code that are of note:
- The 'layouts/attachments_by_role' partial renders the attachments related JSON correctly
- The
all_attachment_joins_by_rolemethod (defined inActsAsAttachmentOwner) generates the JSON to be rendered by the above partial
We provide plenty out of the box to get you started, but of course, your app will likely outgrow the provided functionality, or will need to work with your choice of 3rd party services and libraries. For example:
- You may decide to use a different/additional backing store (Azure or Google) or CDN (CloudFlare or Akamai) instead-of/together-with AWS S3 and CloudFront (that are supported out of the box)
- You may decide to use your own uploader instead of our choice of FineUploader
- You may require additional file types to be viewed directly from the browser, using a specialized JavaScript library for this purpose
All of this is easily possible.
Instructions for doing so are documented in the Rails Attachment model.
Of course, you may also need to write sone code to interface with your chosen backing store and/or CDN (for example, for deleting a file on the backing store, for getting an access URL from the CDN etc.).
We provide FineUploader via the fine-uploader directive. This directive is used in the HTML template of the attachment-library directive, which is responsible for managing uploaded files on screen, and assembles together various parts (the attachment browser, the uploader etc.) for display.
To use your own uploader, you first need to create a directive for it. Then, you need to substitute the fine-uploader tag with your own directive in the template mentioned above. See the attachment-library documentation for more detailed instructions.
On the server side, FineUploader communicates with the Rails FineUploaderController. You will likely have to create a similar controller to interact with your uploader, in the way that it requires.
Also on the server side, FineUploader requies a special template to be rendered, that you will not need when using your own uploader. This template is located in /app/views/layouts/_fine_uploader_tmpl.html, and is rendered in the Rails application layout, i.e. /app/views/layouts/application.html.erb. You can safely remove the line rendering it therein.
The attachment-viewer directive is responsible for viewing attachments in the browser. By itself, it does nothing. Rather, it relies on the AttachmentViewerProvider to give it a concrete implementation of a view (as a string of HTML) depending on the type of file to be viewed. See the documentation therein for detailed instructions on how to provide your own viewers.
To see some examples, look in the app.config section within /app/assets/javascripts/client/angular/app.js, the Angular entry point to the app. In particular, look for instances of AttachmentViewerProvider.addViewerFactory. You'll see for example that we provide a video viewer using the jw-player directive.