janmonschke / backbone-couchdb Goto Github PK
View Code? Open in Web Editor NEWA couchdb connector for backbone with support for real time changes.
Home Page: http://janmonschke.com/projects/backbone-couchdb.html
A couchdb connector for backbone with support for real time changes.
Home Page: http://janmonschke.com/projects/backbone-couchdb.html
Hi there,
I believe that in line https://github.com/janmonschke/backbone-couchdb/blob/master/backbone-couchdb.js#L192
the error variable should actually be e
At least it fails for me with that error.
At least the override of Model::clone is broken at https://github.com/janmonschke/backbone-couchdb/blob/master/backbone-couchdb.js#L298 where is should use this.attributes as 0.9.9 is more strict about the arguments it takes for the constructor.
More might be broken - but thats what we found in a quick survey.
Our workaround:
Backbone.Model::clone = ->
new_model = new @constructor(@attributes)
if new_model.attributes._id
delete new_model.attributes._id
if new_model.attributes._rev
delete new_model.attributes._rev
new_model
Could you please add a license file confirming the MIT license listed in the source code, please?
Found a small bug (or potential bug depending on the version of backbone.js used).
The bug relates to Backbone.sync() having a different parameter signature for the overridden function. Here is the signature of the original function (backbone.js):
Backbone.sync = function(method, model, success, error) {
And the override (backbone-couchdb.js):
// Override the standard sync method.
Backbone.sync = function(method, model, options) {
Notice the "options" vs "success, error"
Solution: Here, I made a few updates to the overridden function to support the change in "options" (backbone-couchdb.js):
// Override the standard sync method.
Backbone.sync = function(method, model, success, error) {
if(method == "create" || method == "update"){
Backbone.couchConnector.create(model, success, error);
}else if(method == "read"){
// Decide whether to read a whole collection or just one specific model
if(model.collection)
Backbone.couchConnector.readModel(model, success, error);
else
Backbone.couchConnector.readCollection(model, success, error);
}else if(method == "delete"){
Backbone.couchConnector.del(model, success, error);
}
// Activate real time changes feed
if(Backbone.couchConnector.enableChanges && !Backbone.couchConnector.changesFeed){
Backbone.couchConnector._changes(model);
}
}
Which is a pain because it means you have to use Backbone.Collection with custom subclasses (or fix the error yourself with
Backbone.Collection::model = Backbone.Model
Looks like a quick and easy task - would be great to have backbone-couchdb added to bower for use with Yeoman and other tools that work with Bower.
http://twitter.github.com/bower/
Defining a package
You can create a component.json file in your project's root, specifying all of its dependencies. This is similar to Node's package.json, or Ruby's Gemfile, and is useful for locking down a project's dependencies.
{
"name": "backbone-couchdb",
"version": "1.2.2",
"main": "./backbone-couchdb.js",
"dependencies": {
"underscore": "~1.3.1",
"backbone": "~0.9.2"
}
}
Put this under your project's root, listing all of your dependencies. When you run bower install, Bower will read this component.json file, resolve all the relevant dependencies and install them.
Authoring packages
To register a new package, it's as simple as specifying a component.json, pushing the package to a Git endpoint, say GitHub, and running:
bower register backbone-couchdb git://github.com/janmonschke/backbone-couchdb
when doc is returned it will list _conflicts and _deleted_conflitcs if they exist, these fields will not be included when the doc is downloaded via it's url. i haven't tested but i think that include docs will provide a similar document as downloading via the url.
i'm not sure, but i think that saving a doc with _conflicts could cause problems.
The _changes() function of the connector calls coll.create(doc), which according to the Backbone API both creates the model on the server and adds it to the collection. But by definition any model in the Couchdb changes feed already exists on the server, so shouldn't it be just coll.add(doc)?
Does backbone-couchdb support deletion changes? By default it uses the by_collection filter. If I just return true from such a filter, then the deletion entries come across in the change feed, of course this breaks backbone-couchdb since it is expecting only pre-filtered models. If the filter actually filters by collection, then i get the right models, but never any deletions in the change feed (makes sense if the deletion occurs before the filter can inspect).
// filters/by_collection.js
function(doc, req) {
return (doc.collection == req.query.collection);
//return (doc.collection == req.query.collection || doc._deleted == "true");
//return true;
}
Is there any relation between andrzejsliwa's backbone-couchdb and this one?
Looking for a "canonical" source for an app I have little probability of successfully crafting.
right now backbone-couchdb can't be installed via the vendor command of couchapp script. Would be cool if you can add metadata.json file to your repo. Ex:
https://github.com/couchapp/couchapp/blob/master/vendor/metadata.json
I think it would be very useful to support the use of CouchDB update handlers.
Comments in the code:
# jquery.couch.js uses the same method for updating as it uses for creating a document, so we can use the `create` method here. ###
update : (model, opts) ->
@create(model, opts)
but jquery.couch.js has db.updateDoc. It's purpose is to execute update handlers.
This would give developers access to the extra power provided by lists and shows - lists, especially. For instance, lists give you access to the userCtx - the name of the user making the query. This can be useful when you're trying to filter records returned to a collection based on the logged in user making the request.
I think this could be implemented relatively easily, either by listening for list or show definitions in options, or by adding a list attribute to collections and a show attribute to models.
Would you entertain a pull request along these lines?
Thanks for the nice module, btw...
Thanks for much for the work you've put into this connector.
Whenever I fetch a collection, a ?keys=null
query sting is appended to the end of the URL, which results in a 500 error:
{"error":"unknown_error","reason":"function_clause"}
My view's map function looks like this:
map: function(doc) { if (doc.collection == 'memories') { emit('doc', doc); } }
When I comment out line 75, there's no longer a query string and there are no problems fetching the collection.
What am I missing that his basic collection fetch doesn't work? And how is the keys feature intended to be used?
When sync
is called with method = "read"
and there is actually a model in the second parameter and not a collection, the current implementation ignores that only the model should be updated and not the complete collection.
I get the following error in the Chrome console when trying to read:
backbone-couchdb.js:79 Uncaught TypeError: undefined is not a function
I think this line:
for doc in data.rows
if doc.value then _temp.push doc.value else _temp.push doc.doc
from:
https://github.com/janmonschke/backbone-couchdb/blob/master/backbone-couchdb.coffee#L75
Should be:
for doc in data.rows
if doc.value then _temp.push doc.value else _temp.push doc
At least that is what I need to handle a view with include_docs turned off. This will still set the id for each model. I am not sure what doc.doc handles though, so I will probably leave it in just in case:
for doc in data.rows
if doc.value
_temp.push doc.value
else if doc.doc
_temp.push doc.doc
else
_temp.push doc
A little context: I have an application with readers and scans, but the only documents I record into Couch are the scans, which contain a reader_description field.
I'd like to have a read-only collection of Readers, containing the distinct set of reader_description fields from the scans collection, so I have a map-reduce view function to emit distinct reader docs:
# to be used with group=true
distinctReadersFromScans:
map: (doc) ->
if doc.collection == 'scan'
readerDoc = { name: doc.reader_description }
emit(readerDoc, doc)
reduce: (keys, values) ->
null
I found this approach on http://stackoverflow.com/questions/2534376/how-do-i-do-the-sql-equivalent-of-distinct-in-couchdb
However, the HTTP response is formatted like this:
{"rows":[
{"key":{"name":"Fake Reader Foxtrot"},"value":null},
{"key":{"name":"Fake Reader Waltz"},"value":null},
{"key":{"name":"Alpha hosting USB Reader Blueberry"},"value":null},
{"key":{"name":"Alpha hosting USB Reader Foxtrot"},"value":null},
{"key":{"name":"Alpha hosting USB Reader Waltz"},"value":null},
{"key":{"name":"Alpha hosting USB Reader Waltz Pro"},"value":null}
]}
and when backbone-couchdb's con.read_connection
is called, only the value is pushed into the collection:
if doc.value then _temp.push doc.value else _temp.push doc.doc
(From backbone-couchdb.coffee#L94)
which means that my models are populated will null, instead of attr objects like { name: 'Fake Reader Foxtrot' }
.
So, I patched the function to handle a null value and emit the key instead:
# JPM: handle group-by mapreduces
if _.isEqual(['key', 'value'], _.keys(doc)) && doc.value == null
_temp.push doc.key
else
if doc.value then _temp.push doc.value else _temp.push doc.doc
I'm pretty new to CouchDB and its idioms. Am I doing this right? Is this patch something that others would find helpful? Does it conflict with some other convention in Couch?
Thanks!
Using collection.fetch() does not return an XHR object.
β¦at least if the cloned object has been saved before.
I think they must be removed to make clone() work as expected.
As I'm not very familiar with CoffeeScript / JavaScript, I don't now how to properly use "super" instead of copying Backbone's Model.clone body.
Nevertheless the following code works (at least for me).
class Backbone.Model extends Backbone.Model
# change the idAttribute since CouchDB uses _id
idAttribute : "_id"
clone : ->
new_model = new @constructor(@)
# remove _id and _rev attributes on the cloned model object
# to have a **really** new, unsaved model object.
# _id and _rev only exist on objects that have been saved,
# so check for existence is needed.
delete new_model.attributes._id if new_model.attributes._id
delete new_model.attributes._rev if new_model.attributes._rev
new_model
Sorry if my question is dump, I'm new to CouchDB.
I would like to build an own app based on the (much appreciated) chat example app.
While I see live updates when someone creates a new model in a collection (e.g. Messages), I don't know how to achieve the same when a model of a collection gets destroyed.
Any thoughts?
I am working on a project which uses backbone-couchdb.
I have trouble getting view
and filter
to work together. It could be the case that it depends on my understand of CouchDB, the backbone-couchdb connector or both.
I am saving notes. An example can be found below. (Id's and revision are striped for brevity.)
{ "key":"notes","value":{"content":"Example","active":true,"edit":false,"x":10,"y":10, "user":"dvb","collection":"notes"}}
With a view active_notes
:
function(doc) {
if (doc.collection == 'notes' && doc.active) {
emit(doc.collection, doc);
}
}
and a filter per_user
:
function(doc, req) {
if (doc.collection == 'notes' && doc.user == req.userCtx.name) {
return true;
}
return false;
}
I would expect the following Backbone.Collection
to only retrieve the "active" documents from the logged in user.
Backbone.Collection.extend({
url : "/notes",
db : {
view : "active_notes",
filter : Backbone.couch_connector.config.ddoc_name + "/per_user"
},
model : NoteModel
});
Instead all "active" documents are retrieved.
Care to shed some light on the interplay between views and filters?
Most of my views emits null to save space so I would like to pass include_docs:true to the jquery.couch view function
Hi there, I recently upgraded backbone and backbone-couchdb in my CouchApp and started noticing a problem with the changes feed.
Backbone-couchdb appears to be requesting a URL like this:
and always gets: "404 Object not found" with the body: {"error":"not_found","reason":"missing json key: filters"}
After some discussion on IRC my guess is that Backbone-couchdb is using more recently CouchDb functionality to "filter" the change stream via a view/map function.
"<rnewson> it probably assumes couch 1.1 where you can point at a map function."
My guess is that this is getting set up per-model, and previously it was a global feed (hence, no filtering).
Is this correct, and if so, is there any way to avoid this filtering (use a global feed) or do I just need to upgrade CouchDb, or downgrade Backbone-couchdb?
Thanks for any feedback!
I have run into a really strange problem since upgrading to 1.0 (rewrite from coffeescript).
When I enable global_changes, it appears collection fetch AJAX calls never return (neither success nor error handler is ever invoked). In cucumber tests I observe that the first couple of fetches take a few seconds, but then inevitably the fetches stop returning at all. I traced it down through jQuery, the AJAX call looks correct but after it is sent nothing is ever heard again, and no request is emitted by the browser. Anecdotally I noticed that if I put alerts in the error handler, and reload the page after some actiivty, I will get a ton of error callbacks all at once. It's almost as if the AJAX requests are queued up behind a long poll or something.
If I set global_changes to false, then everything is snappy and callbacks are invoked immediately.
No, I haven't been able to isolate a small reproducible test case :(
Seen on Chrome 14.0 and Firefox 6 on Linux, with CouchDb 1.0.2 and 1.1. jQuery 1.6.4, Backbone 0.5.3, Underscore 1.1.7.
I'm using this project for the first time. This are the steps to reproduce the error:
According to http://documentcloud.github.com/backbone/#Model-save, the error callback should get the model and the response.
NOTE: Maybe this is because couchdb, and response can't be returned, I'm not sure, I don't know this project or couchdb well enough to be sure.
The jquery.couch.js link in the README points to a defunct url: https://github.com/apache/couchdb/blob/trunk/share/www/script/jquery.couch.js
I searched around for a jquery.couch.js and found one by daleharvey. Maybe they are compatible/identical and that link could be used instead.
A change was made in the recent rewrite which appears to have broken nested collections. The problem is in 'extract_collection_name' - only the first name component will ever be returned. E.g.
/patients/<id> -> patients
/patients/<id>/procedures -> patients
Below is a JS patch which more conservatively strips trailing id but otherwise preserves the rest of the url:
--- backbone-couchdb.js 2011-09-25 17:07:25.287049243 -0400
+++ backbone-couchdb.js 2011-09-25 17:06:17.059060804 -0400
@@ -38,8 +38,18 @@
_name = _name.slice(1, _name.length);
}
_splitted = _name.split("/");
- _name = _splitted.length > 0 ? _splitted[0] : _name;
+
+ if (_splitted.length > 0) {
+ if (model.id == _splitted[_splitted.length -1]) {
+ _splitted.pop();
+ }
+ _name = _splitted.join('/');
+ }
+
+ if (_name.indexOf("/") === 0) {
_name = _name.replace("/", "");
+ }
+
return _name;
},
make_db: function() {
Great app BTW. It's working really well for me other than the fact that there is no way to pull a single model by an attrib that is not the ID.
I think I can work around this by creating a collection with a custom couch view that pulls just one model. But, this seems really hacktastic.
Am I missing the existing way to force model.fetch() to retrieve the model by a non-ID attrib?
I'm trying to use backbone-relational (https://github.com/PaulUithol/Backbone-relational) with backbone-couchdb.js. I want to use backbone-couchdb.js's ability to automatically save model object changes to the database, but it does not work when I combine backbone-couchdb.js with backbone-relational.js. I think that somehow one is overwriting the other's changes to Backbone.Model. So I tried the following:
=== modified file '_attachments/script/lib/backbone-couchdb.js'
--- _attachments/script/lib/backbone-couchdb.js 2012-09-10 21:56:57 +0000
+++ _attachments/script/lib/backbone-couchdb.js 2012-09-10 23:14:04 +0000
@@ -222,7 +222,7 @@
}
};
-Backbone.Model = (function(_super) {
+Backbone.RelationalModel = (function(_super) {
__extends(Model, _super);
@@ -248,7 +248,7 @@
return Model;
-})(Backbone.Model);
+})(Backbone.RelationalModel);
Backbone.Collection = (function(_super) {
But the model objects still don't automatically save to the database.
Is there another way to get backbone-couchdb.js's automatic saving to work again?
I expected to get a jquery deferred object back when I call fetch on a collection - but I am getting undefined. This means I can't hook up a complete callback.
var deferred = myCollection.fetch()
deferred.complete(function(){console.log("success or error have been completed")})
Hi janmonschke,
Thanks for contributing this great adapter. I was hoping you could start versioning so I can properly track changes on my teams' CDN. I'm looking forward to contributing to this as I start to work more with couch. Thanks so much!
function(doc) {
if (doc.collection) {
emit(doc.collection, doc);
}
}
there is no name for this view
A declarative, efficient, and flexible JavaScript library for building user interfaces.
π Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. πππ
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google β€οΈ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.