Answering my own question after few months of trial using different methods. My solution is the following (with Rails).
For any form that requires file upload I would set data-remote="true" and enctype="multipart/form-data" and include rails.js and jquery.iframe-transport.js.
Setting data-remote="true" with rails.js allows me to bind to ajax:success and create the Backbone.js model on success.
HTML:
<form action="/posts.js" method="post" data-remote="true" enctype="multipart/form-data">
<input type="text" name="post[message]" />
<input type="file" name="post[file]" />
<button>Submit</button>
</form>
JavaScript:
You should obviously bind ajax:error to handle error cases.
For me, the data is sanitized in the ActiveRecord model, so don't have to worry too much about the eval statement.
$('form').bind('ajax:success', function(event, data) {
new Model(eval(data)); // Your newly created Backbone.js model
});
Rails Controller:
class PostsController < ApplicationController
respond_to :js
def create
@post = Post.create(params[:post])
respond_with @post
end
end
Rails View (create.js.haml):
Using the remotipart gem.
This will handle the case when the form does file uploads with enctype being set, and when it doesn't.
You could choose to call sanitize on your response here.
= remotipart_response do
- if remotipart_submitted?
= "eval(#{Yajl::Encoder.encode(@post)});"
- else
=raw "eval(#{Yajl::Encoder.encode(@post)});"