Skip to content

Instantly share code, notes, and snippets.

@ianmurrays
Forked from rstacruz/model_caching.coffee
Created November 15, 2012 00:52

Revisions

  1. ianmurrays revised this gist Nov 15, 2012. 1 changed file with 3 additions and 1 deletion.
    4 changes: 3 additions & 1 deletion model_caching.coffee
    Original file line number Diff line number Diff line change
    @@ -63,6 +63,8 @@ class Cache
    if obj.name isnt "" then obj.name else obj.toString()
    else if obj.constructor is Array
    _.map(obj, (item) => @_idString item).join(":")
    else if typeof obj is "number"
    obj
    else
    _.map(obj, (k, v) => "#{@_idString k}:#{@_idString v}").join(":")

    @@ -98,4 +100,4 @@ Backbone.Model::cache = ->
    # Ensures that the item will not be accessible anymore.
    # Add this to your delete success callback.
    Backbone.Model::uncache = ->
    cache.unset [this, @id]
    cache.unset [this, @id]
  2. @rstacruz rstacruz revised this gist Sep 11, 2011. 1 changed file with 2 additions and 0 deletions.
    2 changes: 2 additions & 0 deletions model_caching.coffee
    Original file line number Diff line number Diff line change
    @@ -59,6 +59,8 @@ class Cache
    _idString: (obj) ->
    if typeof obj is "string"
    obj
    else if typeof obj is "function"
    if obj.name isnt "" then obj.name else obj.toString()
    else if obj.constructor is Array
    _.map(obj, (item) => @_idString item).join(":")
    else
  3. @rstacruz rstacruz revised this gist Sep 11, 2011. No changes.
  4. @rstacruz rstacruz created this gist Sep 11, 2011.
    99 changes: 99 additions & 0 deletions model_caching.coffee
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,99 @@
    # ## Backbone model caching
    # This is a simple solution to the problem "how do I make less requests to
    # my server?".
    #
    # Whenever you need a model instance, this will check first if the same thing
    # has been fetched before, and gives you the same instance instead of fetching
    # the same data from the server again.
    #
    # Reusing the same instance also has the great side-effect of making your
    # model changeable from one part of your code, with your changes being available
    # elsewhere in your code without doing `Model#save()`.
    #
    # #### Sample implementation
    # In your model (let's say, `Article`), you will probably will
    # create a new record this way:
    #
    # a = new Article;
    # a.set({ title: "Hello" });
    # a.save({}, {
    # success: function() {
    # this.cache();
    # }
    # });
    #
    # console.log(a.id); //=> 2 [from the server]
    # console.log(a.cid); //=> "c4" [from the client]
    #
    # Elsewhere in your code, you can use `Model.fetch()` to retrieve the
    # same instance. Notice how the client id (`.cid`) is the same as what
    # we had before.
    #
    # a = Article.fetch(2);
    #
    # console.log(a.id); //=> 2 [from the server]
    # console.log(a.cid); //=> "c4" [from the client]
    #

    class Cache
    constructor: ->
    @clear()

    set: (id, block) ->
    @table[@_idString id] = @_use block

    unset: (id) ->
    delete @table[@_idString id]

    get: (id, block) ->
    @table[@_idString id] ||= (if block then @_use(block) else null)

    clear: ->
    @table = {}

    # Uses a given object.
    _use: (obj) ->
    if typeof obj is "function" then obj() else obj

    # Gets a string from any object to be used as a cache key.
    _idString: (obj) ->
    if typeof obj is "string"
    obj
    else if obj.constructor is Array
    _.map(obj, (item) => @_idString item).join(":")
    else
    _.map(obj, (k, v) => "#{@_idString k}:#{@_idString v}").join(":")

    cache = new Cache

    # ### Model.cache [attribute]
    # Returns the cache object.
    Backbone.Model.cache = cache

    # ### Model.fetch(id, args...) [class method]
    # Fetches a model ID from either the cache or the server. The `id` parameter
    # will be the ID of the record you want to fetch, and `args` will be passed
    # onto Backbone's `Model#fetch` (often the `success` and `error` callbacks).
    #
    # # Examples:
    # Document.fetch(2);
    # Document.fetch(2, { success: function() { ... } });
    #
    Backbone.Model.fetch = (id, args...) ->
    cache.get [this, id], =>
    item = new this
    item.id = id
    item.fetch.apply item, args
    item

    # ### Model#cache() [method]
    # Caches the model instance so `Model.fetch` will retrieve it.
    # Add this to your save success callback.
    Backbone.Model::cache = ->
    cache.set [this, @id], this

    # ### Model>uncache() [method]
    # Ensures that the item will not be accessible anymore.
    # Add this to your delete success callback.
    Backbone.Model::uncache = ->
    cache.unset [this, @id]