-
-
Save ianmurrays/4075927 to your computer and use it in GitHub Desktop.
Backbone.js model caching
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# ## 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 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 if typeof obj is "number" | |
obj | |
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] |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment