Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

Already on GitHub? Sign in to your account

Use `url` to specify Store name for portability between storage backends #2

Closed
jasondavies opened this Issue Dec 15, 2010 · 9 comments

Comments

Projects
None yet
7 participants
Contributor

jasondavies commented Dec 15, 2010

I recently developed a prototype using localStorage, and then switched to the CouchDB-based backend. However, I then had to replace all instances of Store with a url property. It seems to me that url could still be used by the localStorage backend, or am I missing something? This would make porting completely painless (it's already pretty easy, but we aim for perfection!)

Owner

jeromegn commented Dec 15, 2010

Interesting. Though "url" is not widely regarded as Universal Resource Location, so it might not work in some people's mind. jashkenas proposed "url" at first too... Mmm...

Let me think about it ;)

Contributor

jasondavies commented Dec 15, 2010

For comparison, the CouchDB backend doesn't really treat it as a URL, it just uses it to name the collection. Perhaps Backbone should use a more descriptive name.

meecect commented Feb 2, 2012

I'd like to see this as well. I'm currently working on a project that will initially use localstorage but will eventually migrate to a REST interface. Having a smooth upgrade path would be very nice.

Additionally, I see lots of examples of apps and plugins that use the 'url' for functionality. For example, backbone-relational uses url on a nested collection to return children models. This has been very difficult for me to integrate with localstorage.

One approach I have been thinking about is perhaps the ability to override the behavior of store and fetch. For example, I may want to use localstorage, but I want children objects to store by a foreign key and I want fetch to return only subsets while expanding child objects etc. Do you have any advice on that?

Owner

jeromegn commented Jan 14, 2013

After 2 years of thinking (not true, just stumbled on this now that I'm cleaning up the repo), maybe something like this could work:

var Collection = Backbone.Collection.extend({
  url: Backbone.LocalStorage("collectionStore");
});

And then somehow override url on Backbone.Model to figure out if it's using Backbone.LocalStorage...

Having also encountered issues with this, the issue here is that it still requires altering the model to fit the storage backend, which I believe is the original complaint: it makes switching storage backend slightly harder (all models have to be edited), and it makes models reuse (across projects or models from third parties e.g. using existing backbone-based "widgets") significantly harder as potentially third-party or library code has to be edited to move to/from localStorage, it's not just a question of correctly setting up Backbone.sync.

Why not do something similar to the original sync but use the URL as a LocalStorage key rather than a URL? (the URL would have to be munged slightly to remove the id for some methods, but that's about it).

And maybe if mixed storage backend and routing across them is an important use case, provide a shim (maybe in an other project) mapping models or base URLs to storage backend functions?

Owner

jeromegn commented Jan 29, 2013

@masklinn so how does Backbone know to use the localStorage adapter if there's no mention of it anywhere?

Backbone.localStorage is not replacing Backbone.sync anymore. It simply uses localSync if the model or collection has the localStorage property present.

so how does Backbone know to use the localStorage adapter if there's no mention of it anywhere?

Backbone does not, the adapter is installed by replacing Backbone.sync explicitly. If the developer wants to route all models to local he simply replaces Backbone.sync with localeSync (or whatever), otherwise he installs a custom Backbone.sync replacement which does the dispatching between localeSync and the original sync based on whatever criteria.

This way, the model & collection implementations and the synchronization/persistence strategy are decoupled and independent.

Contributor

andriijas commented Jan 29, 2013

I think I like this solution...

Hi,

Context: I'm writing a book on Backbone.Marionette.js (https://leanpub.com/marionette-gentle-introduction) and I wanted to use local storage to avoid explaining all the server back ends. But at the same time, I wanted the "footprint" of using localStorage to be minimal (i.e. have the app's code look "normal").

My solution can been seen here: https://github.com/davidsulc/marionette-gentle-introduction/blob/3b441c9355ac49348eebb3eca27c06ec79b9f64d/assets/js/apps/config/storage/localstorage.js

It defines a mixin that reuses the url or urlRoot value (as appropriate) as the storage key and configures localSotrage on the model/collection's prototype. To use it in the app, we just need to call it like this:

Entities.configureStorage(Entities.ContactCollection);

(e.g. see line 14 here: https://github.com/davidsulc/marionette-gentle-introduction/blob/bcb16d45876c321e071624319bf87c8a9cf1d656/assets/js/entities/contact.js#L14 )

Thoughts ?

@scott-w scott-w closed this Feb 28, 2017

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment