开发者

Nested forms, inline uploads, and progress bars with Carrierwave in Rails

I have rather esoteric usecase for nested forms, multi-file uploads, and progress bars in Rails. I haven't found any online discussions about precisely about this so far. If I have overlooked something, I am sorry. Please correct me.

Here is what I want:

  1. A given form has multiple dynamic fields. One of which is 'attach a file'.
  2. For this 'Attach a file', I would like an interface which is essentially similar to gmail.
  3. That interface enables you to :
    1. click 'attach file'.
    2. select a local file, which starts uploading immediately in the background, giving you a progress bar in the mean time.
    3. this allows you to write your message, or add more files.
    4. You can cancel a live upload and even delete attachments after the fact by un-checking a box.

Here are the models and associations I am working with.

  1. I have a model Recording which has many AudioFiles.
  2. Each AudioFile contains audio data, as well as metadata like size, type, date created etc.
  3. A Recording has several other child collections as well.

Here is how the 'Create Recording' form should behave:

  1. It should enable the user to add multiple number of child fields, including multiple audio files..
  2. So far, I am using the excelle开发者_JS百科nt Nested Form (https://github.com/ryanb/nested_form) gem to create the non-AudioFile children of a Recording. IT works brilliantly.
  3. What I want is to be able to have similar nested fields to upload multiple audio files, asynchronously, with progress indicators, and with an ability to cancel or delete uploaded files.

There are many resources which demonstrate how to use uploaders in conjunction with carrierwave to store files with progress information. For instance, https://github.com/yortz/carrierwave_jquery_file_upload, and https://github.com/blueimp/jQuery-File-Upload/wiki/Rails-setup-for-V5 .

Essentially, what these examples do is to generate a request from one of these uploaders which is directed to a controller create action for a model which has a carrierwave uploader attached to it. I have got this much to work OK.

What I can't figure out is how to do this in a nested form context. The tricky bits are:

  1. Suppose I write up the AJAX to do a post from a 'Create Recording' form, and have that post create a new AudioFile record. How do I associate that audio file with the as-yet-un-created recording?
  2. If the user aborts the transaction, how will the AudioFile record thus created be cleaned up?

I can think of hacky-ways to do both of the above, but I am wondering if there are more elegant approaches. I am rather new to rails so I am guessing that I am not using it to the fullest.

Thanks, Apurva


I thought I would contribute back to the community by sharing how I solved this problem.

To summarize, the major problem was to reconcile the behavior of CarrierWave, nested forms, and fine grained control of file uploads.

The crux of the issue was that Nested Forms create the root record and all its associations in a single POST operation to the #create action of the root Controller.

In the example above, the Recording model was the root, while AudioFile, Note, and Categorization were the associations to be created along with a Recording.

So with Nested Forms, I would have to create all these records in a single POST, which would preclude the possibility of canceling uploads in isolation, or uploading in parallel with adding other fields (like Notes).

That would not make for a good user experience. My solution was really simple:

  1. I chose not to use nested forms.
  2. Recording#create would always be called with empty parameters. The Recording attributes would get sensible default values in the create operation.
  3. The user would only see the Recording#edit page.
  4. On the Recording#edit page, I had independent controls for CRUD operations on the associated models which would route to different controllers through AJAX calls. This worked because each associated model had a valid recording_id to use.
  5. The various controllers would return HTML fragments which would be written into the main recording page.

This enabled inline editing of all the fields on the Recording page, even though these fields mapped to different (associated) models. Thus the user would be able to upload multiple files, add notes while they were uploading, play back already uploaded files, and cancel uploads at will.

As a result the whole user experience was a lot smoother. This would never have been achievable with Nested forms by definition.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜