Hello there, A few days ago I was looking for a step-by-step tutorial on how to manage file upload with the tools I mention in the title, and I couldn't find one tutorial, so I decided to write one myself!
In the first part of the tutorial, I show you a gallery made in Backbone plus Coffeescript, Haml, Eco templates, the jQuery file upload tool, Rails, Paperclip, and Amazon AWS.
First of all, we need to create a new Rails project:
$ rails new jqueryfileuploadbackbone
$ cd jqueryfileuploadbackbone
The Gemfile configuration should be the following:
source 'https://rubygems.org'
# Bundle edge Rails instead:
# gem 'rails', :git =>; 'git://github.com/rails/rails.git'
gem 'haml'
gem 'jquery-rails'
gem 'rails', '3.2.11'
gem 'paperclip', '~>; 3.4.0'
gem 'aws-sdk', '~>; 1.6.0'
gem 'aws-s3'
#gem 'mysql2'
gem 'pg'
gem 'devise'
gem 'jquery-fileupload-rails'
gem 'rb-readline'
gem 'debugger'
# Gems used only for assets and not required
# in production environments by default.
group :assets do
gem 'backbone-on-rails'
gem 'backbone-support'
gem 'coffee-rails', '~>; 3.2.1'
gem 'eco'
gem 'haml_assets'
gem 'sass-rails', '~>; 3.2.3'
gem 'sass'
# See https://github.com/sstephenson/execjs#readme for more supported runtimes
# gem 'therubyracer', :platforms =>; :ruby
gem 'uglifier', '>= 1.0.3'
end
group :test, :development do
gem 'fabrication'
gem 'guard-rspec'
gem 'rspec-rails'
end
# To use ActiveModel has_secure_password
# gem 'bcrypt-ruby', '~>; 3.0.0'
# To use Jbuilder templates for JSON
# gem 'jbuilder'
# Use unicorn as the app server
# gem 'unicorn'
# Deploy with Capistrano
# gem 'capistrano'
# To use debugger
# gem 'debugger'
Now we need to install all the Gems using the next command
$ bundle install
Now we need to create a model to save our images and additional data, I'll create one called 'qrcodes', where 'image' will be where I save the image name, which is a requirement of the Paperclip Gem.
$ rails generate model Qrcode description:string
$ rake db:setup
Now we need to prepare our model to upload images, for this effect just run the next command generator for Paperclip, this is where we specify our model and the attribute where we'll save our images.
$ rails generate paperclip Qrcode image
Now we need to run all of our migrations
$ rake db:migrate
Now comes the moment to generate our Backbone structure (models, views, routes, etc), we can use Scaffold like the following:
$ rails g backbone:install
Now we continue with the creation of our controller and two methods to upload and show all of the images that were transferred.
$ rails g controller qrcodes index create --skip javascript
After using the previous command, we are going to create our routes to use it, for this we're going to edit the file routes.rb located in
config/routes.rb
We are going to declare the next two lines if they don't already exist
get 'qrcodes/index'
root to: 'qrcodes#index'
Now we need to delete the public index file, to show the root page index in the qrcodes controller, used in the previous step.
public/index.html.erb
If we have done everything correctly, we can now run our server using the rails server command so we can receive pop alerts in the address:
http://localhost:3000
Now let's modify the following file to enable our routes:
app/assets/javascripts/jqueryfileuploadbackbone.js.coffee
Adding the following code:
window.Jqueryfileuploadbackbone =
Models: {}
Collections: {}
Views: {}
Routers: {}
ManageImages: ->
new Jqueryfileuploadbackbone.Routers.Qrcodes()
alert 'in backbone'
Backbone.history.start()
$(document).ready ->
Jqueryfileuploadbackbone.ManageImages()
At this point we need to verify that all works fine. If we had any issues with Javascript we need to check the application.js file. For example, I had to change the original content because I had problems with the Backbone templates and I fixed it like this:
//= require jquery
//= require jquery_ujs
//= require_self
//= require underscore
//= require backbone
//= require jqueryfileuploadbackbone
//= require_tree ../templates/
//= require_tree .//models
//= require_tree .//collections
//= require_tree .//views
//= require_tree .//routers
Now we're going to edit our routers file to show our images list, the file is:
app/assets/javascripts/routers/qrcodes_router.js.coffee
And add the following content:
class Jqueryfileuploadbackbone.Routers.Qrcodes extends Backbone.Router
routes:
'' : 'showManageImages'
showManageImages: ->
@collection = new Jqueryfileuploadbackbone.Collections.Qrcodes()
@collection.fetch()
view = new Jqueryfileuploadbackbone.Views.QrcodesIndex collection: @collection
$('#container-app').html view.render().el
In the previous code we can see that we need to use our collection to show all the images, but it is necessary to declare first the right routes in the config/routes.rb file like the following:
scope api do
resources :qrcodes, format: false
end
Now we are going to use our model to fetch all the data from the qrcode table, for that we use the file:
app/assets/javascripts/models/qrcode.js.coffee
And we are going to specify the routes that we declared in the routes file, this is what I have:
class Jqueryfileuploadbackbone.Models.Qrcode extends Backbone.Model
urlRoot: 'api/qrcodes'
In the same way, we are going to edit the collection file
app/assets/javacripts/collections/qrcodes.js.coffee
Its content is:
class Jqueryfileuploadbackbone.Collections.Qrcodes extends Backbone.Collection
url: 'api/qrcodes'
model: Jqueryfileuploadbackbone.Models.Qrcode
Important note: In this case I'm using Coffescript and it's of great importance to be careful with the indentation spaces at all times.
If you remember, in the Backbone router file we declared an div "container-app", this will be used to attaching our Backbone app in ROR, the view in charge of doing that is:
app/views/qrcodes/index.html.erb
We are using haml (included in the Gemfile), and now we're going to substitute the file extension .haml for .erb
app/views/qrcodes/index.html.haml
The contents of the file are:
%h1 List of Images
#container-app
Now we are going to edit our qrcodes_index.js.coffee view
app/assets/javascripts/views/qrcodes_index.js.coffee
As an example, we could use:
class Jqueryfileuploadbackbone.Views.QrcodesIndex extends Backbone.View
template: JST['qrcodes/index']
render:->
@$el.html @template
@
Continuing working with haml, we need to add the .haml extension to use it in our Eco template. The original file was:
app/assets/templates/qrcodes/index.jst.eco
Now it should look like this:
app/assets/templates/qrcodes/index.jst.eco.haml
And we need to a link:
=link_to 'Add new Image', '#qrcode/add'
And now get to the interesting part, where we deal with file uploads. To do this we will create a new view:
app/assets/javascripts/views/qrcodes/add_view.js.coffee
The content of the file to use the jQuery File Upload plugin in Backbone is:
class Jqueryfileuploadbackbone.Views.QrcodesAddView extends Backbone.View
template: JST['qrcodes/add']
render: ->
@$el.html @template
@uploadQrcode()
@
uploadQrcode:=>
@$el.fileupload
add: (e, data)->
$('#qrcode_image').hide()
$("#fileupload-loading").html 'Cargando...'
data.submit()
formData: [
name: 'authenticity_token'
value: $("meta[name=\'csrf-token\']").attr('content')
]
done: (e, data) ->
window.location = '/'
And add template with the following content:
The template file name is:
app/assets/templates/qrcodes/add.jst.eco.haml
The content of the form to upload images is:
= form_tag 'api/qrcodes', :multipart => true, :id => 'fileupload' do
.fields
= file_field(:qrcode, :image)
#fileupload-loading{style: 'height: 50px; width: 200px;'}
%br
Now let's add our route in qrcodes_router.js.coffee to use our new view to add images
The updated content should be:
class Jqueryfileuploadbackbone.Routers.Qrcodes extends Backbone.Router
routes:
'' : 'showManageImages'
'qrcode/add' : 'addNewImage'
showManageImages: ->
@collection = new Jqueryfileuploadbackbone.Collections.Qrcodes()
@collection.fetch() view = new Jqueryfileuploadbackbone.Views.QrcodesIndex collection: @collection
$('#container-app').html view.render().el
addNewImage : ->
view = new Jqueryfileuploadbackbone.Views.QrcodesAddView
$('#container-app').html view.render().el
Now we need to declare our file upload plugin:
app/assets/javascripts/application.js
And we need to add the jquery file upload Gem (included in the Gemfile)
//=require jquery-fileupload/basic
This the moment to configure the Paperclip gem to manage uploads in our server, first edit the file
app/models/qrcode.rb
The last content you need to add is:
class Qrcode < ActiveRecord::Base
attr_accessible :description, :image
has_attached_file :image,
:url => '/system/qrcodes/:filename'
end
Afterwards, we edit the qrcodes_controller.rb file with the following code:
class QrcodesController < ApplicationController
respond_to :json
def index
end
def create
respond_with Qrcode.create(params[:qrcode])
end
end
Additionally, run all the migrations:
$ rake db:migrate
And now we can run our server
$ rails server
Let's test what we did. First, click in the add new image link. Then, browse for an image with the right format in the form. If the file uploads, we have a working application!
Locally, the file should be located in the public/qrcodes directory.
In another tutorial I will teach you how to list and delete images.
Hope you found this tutorial useful. You can find the repo in github at:
https://github.com/heridev/jqueryfileuploadbackbone
See you next time!