Skip to content

Instantly share code, notes, and snippets.

@ggoodman
Created December 21, 2011 20:33
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ggoodman/1507576 to your computer and use it in GitHub Desktop.
Save ggoodman/1507576 to your computer and use it in GitHub Desktop.
Lumbar wrapper for Backbone.js Models using Deferred objects and declarative persistence

lumbar.Model / lumbar.Collection

Class-level, Static API

@persist(attribute, [optionsOrSerializerFunction])

Instruct lumbar that this attribute should be included in the object returned by model.toJSON().

If a serializer function is included, the attribute's value will be passed through this function.

Alternatively, an options object can be passed in with save and/or load callbacks that will

The serializer function will be called with two arguments, value and attribute. This function should represent a serialized (String) version of the value.

Note: If no calls are made to Model.persist() then lumbar will assume that all attributes should be persisted normally as per Backbone.js behaviour.

@expose(attribute, [filterFunction])

Instruct lumbar that this attribute should be exposed to views in model.toViewModel(). Optionally specify a filter function to transform/serialize the attribute's value.

The filter function will be called with two arguments, value and attribute.

Note: If no calls are made to Model.expose() then lumbar will assume that all attributes should be persisted normally as per Backbone.js toJSON() behaviour.

Example:

class MyAuthor extends lumbar.Model
  @persist "firstName"
  @persist "lastName"

  @expose "fullName", ["firstName", "lastName"], (firstName, lastName) ->
    "#{firstName} #{lastName}"

class MyNewsItem extends lumbar.Model
  @persist "title"
  @persist "description"
  # @author is a model, save only the model's id
  @persist "author",
    save: -> @author.id
    load: (author_id) -> @author = new MyAuthor(id: author_id)
  @persist "updated", -> +new Date()
  

Enhancements of Backbone.js

Asynchronous methods return promise objects

The following asynchronous methods no longer accept an options object with success and failure callbacks. Instead, they return Promise objects of jQuery Deferred objects.

lumbar.Model:

  • model.save()
  • model.fetch()
  • model.destroy()

lumbar.Collection:

  • collection.create()
  • collection.fetch()
((lumbar) ->
lumbar ||=
version: "0.0.2"
lumbar.Deferred = jQuery.Deferred or _.Deferred
class lumbar.Model extends Backbone.Model
@persist: (attribute, filter) ->
@persisted ||= {}
@persisted[attribute] = filter or (value) -> value
@
@expose: (attribute, dependentAttributes, valueBuilder) ->
@exposed ||= {}
@exposed[attribute] = {dependentAttributes, valueBuilder}
@
constructor: ->
self = @
oldInit = self.initialize
self.initialize = ->
if self.constructor.exposed
for attribute, {dependentAttributes, valueBuilder} of self.constructor.exposed
initial = []
for dependency in dependentAttributes
initial.push self.get(dependency)
self.bind "change:#{dependency}", (model) ->
args = []
args.push model.get(attr) for attr in dependentAttributes
toSet = {}
toSet[attribute] = valueBuilder.apply(model, args)
model.set toSet
toSet = {}
toSet[attribute] = valueBuilder.apply(self, initial)
self.set toSet
oldInit.call(self, arguments...)
super(arguments...)
toJSON: ->
raw = super()
unless @constructor.persisted then raw
else
json = {}
for attribute, save of @constructor.persisted
json[attribute] = save.call(@, raw[attribute], attribute)
json
save: (attrs, options) ->
self = @
dfd = new lumbar.Deferred
super attrs, _.extend {}, options,
success: (args...) -> dfd.resolveWith(self, args)
error: (args...) -> dfd.rejectWith(self, args)
dfd.done -> self.saved = _.clone(self.attributes )
dfd.promise()
destroy: (options) ->
self = @
dfd = new lumbar.Deferred
super _.extend {}, options,
success: (args...) -> dfd.resolveWith(self, args)
error: (args...) -> dfd.rejectWith(self, args)
dfd.promise()
fetch: (options) ->
self = @
dfd = new lumbar.Deferred
super _.extend {}, options,
success: (args...) -> dfd.resolveWith(self, args)
error: (args...) -> dfd.rejectWith(self, args)
dfd.done -> self.saved = _.clone(self.attributes )
dfd.promise()
class lumbar.Collection extends Backbone.Collection
create: (attrs, options) ->
self = @
dfd = new lumbar.Deferred
super attrs, _.extend {}, options,
success: (args...) -> dfd.resolveWith(self, args)
error: (args...) -> dfd.rejectWith(self, args)
dfd.promise()
fetch: (options) ->
self = @
dfd = new lumbar.Deferred
super _.extend {}, options,
success: (args...) -> dfd.resolveWith(self, args)
error: (args...) -> dfd.rejectWith(self, args)
dfd.promise()
)(window.lumbar)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment