Skip to content

Instantly share code, notes, and snippets.

@ekampp
Created September 8, 2012 20:04
Show Gist options
  • Save ekampp/3679278 to your computer and use it in GitHub Desktop.
Save ekampp/3679278 to your computer and use it in GitHub Desktop.
Backbone synchronizable collection.
#
# In order to expose the `where` and `query` methods (see query.js) we extend
# from the QueryCollection class instead of the standard backbone collection.
#
class Backbone.StandardCollection extends Backbone.QueryCollection
# Checks that the csrf token is present, otherwise fetch it.
csrfToken: ->
if $("head meta[name='csrf-token']").length > 0
debug.log "CSRF token present."
return true
else
debug.log "CSRF token not present. Fetching it.."
$.get '/authenticity_token', (response)=>
$("head").append($("<meta>").attr("name", "csrf-token").attr("content", response))
# Synchronize the local storage with the database
# TODO: Extend every collection with this method! <emil@kampp.me>
synchronize: ->
# Don't synchronize if there is no local storage defined for the collection!
unless @localStorage
debug.warn "No local storage defined!"
return false
# Start synchronization
debug.log "Attempting contact with backend.."
$.when(ping(), @csrfToken()).then =>
debug.log "Connection with backend successfull. Synchronizing.."
syncs = []
_.each @models, (record)=>
data = @localStorage.find(record)
# If the record doesn't exist in local storage, create it there!
if data == null
debug.log "This is a new record, create it."
Backbone.sync "create", record,
success: ->
error: ->
data = record.attributes
# Checks if the record needs creation or update
client_id = data.id
new_record = true if /-/g.test client_id
# If the user has marked the record for syncronization
if data.needs_synchronizing == true
debug.log "Synchronizing record " + record.get("id") + ".."
action = if new_record then "create" else "update"
syncs.push Backbone.ajaxSync action, record,
success: (data)=>
# Update record with response
record.set(data, { silent: true })
# If a new record was created, replace the one in local storage
# NOTE: Getting the record id returns a string instead of an
# integer. Typcasting both to be sure! <emil@kampp.me>
if parseInt(record.get("id"), 10) != parseInt(client_id, 10)
debug.log "Server responded with a different id, remove and reinsert in local storage."
Backbone.sync "destroy", record,
success: =>
Backbone.sync "create", record,
success: =>
error: =>
error: =>
# If the record was destroyed (deleted at set to something) remove
# it from local storage.
else if record.get("deleted_at") != null
debug.log "Server marked the record as deleted, purge from local storage,"
Backbone.sync "destroy", record,
success: =>
error: =>
# The record was updated, do the same in local storage
else
debug.log "Server updated the record, update local storage."
Backbone.sync "update", record,
success: ->
error: ->
# When all the ajax requests have finished, notify the user
$.when(jQuery, syncs).then =>
@global_dispatcher.trigger "flash", "Synchronized data with server."
# If the remote data has been updated at a later date than the local one,
# overwrite the local storage with the remote.
if new Date(data.updated_at) < new Date(record.get("updated_at"))
Backbone.sync "update", record,
success: ->
error: ->
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment