pouchdb-community / ember-pouch Goto Github PK
View Code? Open in Web Editor NEWPouchDB/CouchDB adapter for Ember Data
License: Apache License 2.0
PouchDB/CouchDB adapter for Ember Data
License: Apache License 2.0
The default behavior of DS.JSONSerializer
is to not serialize the many side of bidirectional hasMany relationships. See emberjs/data#2494 for links to discussion about this.
The upshot for ember-pouch
is that the contents of a bidirectional hasMany relationship isn't saved or loaded when working from the many side. E.g., say you have these models:
// app/models/person.js
export default DS.Model.extend({
sandwiches: DS.hasMany('sandwich', { inverse: 'owner' })
});
// app/models/sandwich.js
export default DS.Model.extend({
owner: DS.belongsTo('person')
});
In this case you won't be able to load or save a person's sandwiches from the person. (You will be able to if you remove owner
from sandwich, though.)
The workaround for this that other similar adapters use (ember-localstorage-adapter, ember-indexeddb-adapter) is to provide a serializer which forces these associations to be serialized on the hasMany side (as well as the belongsTo side). I'm doing this now in my own application to work around this issue.
Unfortunately this requires copying a bunch of code from JSONSerializer (hence emberjs/data#2494). It also duplicates the information about the relationship, requiring both sides to be saved manually whenever the relationship changes.
I'm not sure if there's a practical better solution. It appears that the ember-data solution is to have the server use different serializations for reads vs. writes, but that doesn't work for a local database. One idea I had was that the adapter could look up the IDs for the hasMany relationship dynamically — since all the data is local this might work, but it also might be complex to get right.
The incorporation of the call to changes
is causing these warnings for me:
(node) warning: possible EventEmitter memory leak detected. 11 listeners added. Use emitter.setMaxListeners() to increase limit.
I see this was discussed in the PouchDB repository, but the resolution there doesn’t apply, since I’m ember-pouch
is starting the change listener, rather than me.
I verified that this was the cause of the warning by removing the call to changes
: the warning went away.
The warning comes as soon as I load anything from PouchDB, so the pull request I just made, #24, doesn’t help, since it only applies when the application is being destroyed.
I've got a very basic application which uses Pouch/CouchDB, and I've got Ember Pouch successfully pulling down and loading documents on newly connecting clients. I'm finding the initial population of data and updating of the page view to be pretty slow though. I've seen discussion of loading db.allDocs to be painful for applications with lots of records, but I only have 25 in my app (including the design doc), and it's not going to grow by more than a few documents every several months. Yet it takes upwards of 3-4 seconds on new clients to display any data. My production site is being hosted on Cloudant, and my local instances don't do much better.
Here's my adapter. Is there anything obvious I can be doing to speed up load times? I've tried using only the db.allDocs, or the db.changes, but I can't really find any difference between the two in results, and the docs aren't super clear (which I'll get to in a second).
I have a static page (hard coded into the template file) that loads to begin with. Ideally, I'd like to start downloading a few records in the background while folks are reading that, but the network doesn't try to acquire the Pouch copy until I've switched routes. Setting my index page to retrieve data it doesn't use just to initiate the PouchDB creation seems like bad form, but I don't see any scenarios documented for bootstrapping specific content, only broad strokes examples for grabbing all docs, a single doc by id, or changed docs.
What I'm finding though is that there's not really any great descriptions of what each option means, or moreover, the meanings are muddled. For instance, when I get allDocs, am I getting the current version of every doc, or am I getting every revision of every doc? From what I'm seeing in my console, I'm receiving the latter (519 requests and 90MB of data). When I request db.changes, I would presume I'm only receiving items that have changed since my last visit, and expect it to do nothing on my first visit as everything should new to me for the first visit, but that's not the case.
I think there are a few user scenarios that might be helpful to add to the docs, so that people starting out (like myself) have a foothold on what to use where. There are great examples that I've copied from, which have been quite helpful getting set up, but there's not a ton out there on the "whys" and "what fors". Going back to the CouchDB docs don't really help with these problems as they don't get into any more detail either. I would be happy to contribute a PR to the documentation, but I could some guidance on the above in order to help.
Thanks!
Hi!
In my application I want to have separate database for each Ember model called Project
. The project is something like a container for model Todo
.
And one of my usecases is just to show all todos for project. But I have separate db for each of them.
So how can I toggle between my dbs "on the fly"?
My idea is to to reopen Todo
adapter and redefine db like this:
if (!Ember.isEmpty(project.get('projectDbName'))) {
var dbName = project.get('projectDbName');
var db = new PouchDB(dbName);
var remote = new PouchDB('http://127.0.0.1:5984/%@'.fmt(dbName));
var doSync = function() {
db.sync(remote, {
live: true
}).on('error', function() {
setTimeout(doSync, 1000);
});
}
doSync();
TodoAdapter.reopen({
db: db
});
}
But this seems to be not working.
On the line:
var req = global.indexedDB.open(name, ADAPTER_VERSION);
firefox reports"InvalidStateError"
In Chrome and IE this works fine.
I get a lot of 'DEPRECATION: Usage of typeKey
has been deprecated and will be removed in Ember Data 1.0. It has been replaced by modelName
on the model class.' messages in my console lately.
The warning has been introduced with 1.0.0-beta.18:
https://github.com/emberjs/data/blob/master/CHANGELOG.md#release-100-beta18-may-18-2015
Hi,
I'm rather new to Ember & Pouch but I've setup a small test project where I list a set of items. Everything like adding and updating seems to work but for single problem, if I delete a document (server-side) the changes aren't reflected until I refresh the page.
I've the afterModel function as per the docs implemented and updating a document server side is reflected on the page. I'm unsure about the issue but a potential problem is that every document on my couchdb has the id in the form "post_2_*" where post is my model name and 2 is (for some reason) always the same for every document. The * part does show some sort of unique identifier.
As pointed out by @broerse, it's kind of annoying that you have to do this with Ember Pouch, but you don't need to for Ember Fire.
Hi,
Firstly, just wanted to let @nolanlawson and other contributors you have done an awesome job putting this together. Was literally a life-saver for us as we are heavy users of Ember with CouchDB/Couchbase Lite/PouchDB! Hopefully we can contribute too in the new year.
As there isn't much chance of a question for this addon getting answered in stackoverflow just yet, hope you dont mind me listing it here.
When a record is saved back to the DB, it gets an ID like this:
staffMember_2_C7BD604D-182C-23A4-A024-7D582F2F396D
I obviously understand the first word is the model and the long ID string is the UUID. But what is the significance of the number 2 between them?
Main reason I ask, is in one particular project we are generating documents from outside ember-pouch too, so I want to make sure I understand all the current conventions.
Thanks again and great work!!!
It looks like I got attachments saving correctly using an attachment transform. However, when I pull the record back out stub
is set to true and data
is undefined when I look at the data in my deserializer.
Is there any way to get relational pouch to automatically retrieve attachments? I.e. pass {attachments:true} like you can with regular pouch?
I've been slow to respond to issues recently, mostly due to going on vacation for the past few weeks.
I'd hate to see progress stalled on this project due to my own lack of free time, so if the other maintainers could please post their npm usernames here, I'd be happy to add them as npm authors so that they can publish. :)
So this is a problem that occurred to me recently: the changes()
feed actually includes conflicting and non-winning leaf revisions, which presumably you don't want to show in a list of DOM elements because it looks like duplicates.
So we will have to add some fancier logic to the changes()
feed to check for non-winners. Hopefully we won't need to add any new APIs for conflict resolution, though, because that should be possible via PouchDB itself.
I don't know for sure if this is a ember-pouch thing but it seems ember-data gives an error on destroyRecord().
json_serializer.js:544 Uncaught TypeError: undefined is not a function
In the serializeAttribute: sub on: snapshot.attr
If I go back to 1.0.0-beta.14.1 all works again
Is there somebody who can confirm Ember-Pouch and destroyRecord() works with Ember-Data 1.0.0-beta.15 ?
I will investigate further.
I'm new to couch and pouch, but this addon was suggested as a way to persist data across page reloads, and so far it seems like a really great solution.
I've noticed tombstones are getting left behind when I use destroyRecord() in ember, e.g.
{_deleted: true, _doc_id_rev: '...'}
. I think I know the theory behind these, and would like to know if there's a way to garbage collect them, or disable them, in an app-specific / model-specific fashion.
Also which system introduces the use of tombstones, so I can figure out which docs to read about their semantics: couchdb, pouchdb, relational pouch? I think it'd be an interesting thing to add to the readme for people who need to explore the system's behaviour.
Here the model:
App.Article = DS.Model.extend({
title: DS.attr('string'),
comments: DS.hasMany('comment'),
rev: DS.attr('string')
});
App.Comment = DS.Model.extend({
text: DS.attr('string'),
article: DS.belongsTo('article'),
rev: DS.attr('string')
});
After save() is the hasMany-assoziation array empty. if I omit article: DS.belongsTo('article'), then the comments-array is filled.
Sorry for additional questions, but I am a little confused after reading the docs for both ember-pouch and relational-pouch.
With ember-pouch, are the document id's automatically set to "pokemon_1" or "trainer_2" as mentioned in the README for relational-pouch?
Also, does ember-pouch include the relational-pouch plugin and call the appropriate db.setSchema() methods automatically?
I was having intermittent failures in my acceptance tests that I was able to fix using this technique of setting a promise on the controller that the test waits for the resolution of. It seems unfortunate to me to add test-specific code to the application, so I’ve been looking into how the andThen
acceptance test helper determines when asynchronous operations are complete so it can check the expectations.
I think the key code is here. This line would be helpful if the application were backed by a REST/AJAX database:
// 2. If there are pending Ajax requests, keep polling
if (Test.pendingAjaxRequests) { return; }
Elsewhere, they register to listen for AJAX events and operate on the counter that way:
jQuery(document).on('ajaxSend', incrementAjaxPendingRequests);
jQuery(document).on('ajaxComplete', decrementAjaxPendingRequests);
So, my question, is there a way I can detect an ongoing PouchDB operation and delay the progression of the test until the operation is complete? I looked at PouchDB.on
, but it’s apparently only for created
and destroyed
events.
Maybe there’s a way to include this kind of functionality in ember-pouch
to facilitate acceptance tests. Like setting a flag before a call to this.db.rel.find
and the like, and unsetting it when the operation completes. Then I could override `setupForTesting' and pretend that a PouchDB operation is an AJAX operation, for the purposes of testing.
Ideally, ember-testing
would have a facility where ongoing asynchronous operations can be registered to delay test progression, but I’m not optimistic on that happening.
This may not be something you want ember-pouch
to be concerned with, though, understandably.
- Using store.getById() has been deprecated. Use store.peekRecord to get a record by a given type and ID without triggering a fetch
- DS.Model#isDirty has been deprecated please use hasDirtyAttributes instead
- You tried to look up 'store:main', but this has been deprecated in favor of 'service:store'
I think these are all coming from the change watcher.
HI,
I'm new with Ember and so with ember-pouch. I try to set up the adapter but i'm facing some problems. I use Ember 1.11.3, Ember data 1.16.1 with ember-pouch 1.2.5
This is my app/adapter/application.js
import config from '../config/environment';
var remote = new PouchDB(config.remote_couch);
var db = new PouchDB(config.local_couch);
PouchDB.debug.enable('*');
db.sync(remote, {
live: true, // do a live, ongoing sync
retry: true // retry if the conection is lost
});
export default EmberPouch.Adapter.extend({
db: db
});
And this is errors:
adapters/application.js: line 3, col 18, 'PouchDB' is not defined.
adapters/application.js: line 4, col 14, 'PouchDB' is not defined.
adapters/application.js: line 5, col 1, 'PouchDB' is not defined.
adapters/application.js: line 11, col 16, 'EmberPouch' is not defined.
I've tried to add this line on top of application.js
import PouchDB from 'ember-pouch';
import EmberPouch from 'ember-pouch';
but i've got this error :
Could not find module `ember-pouch` imported from `myapp/adapters/application`" "requireFrom@http://localhost:4200/assets/vendor.js:119:1
One idea what i did wrong?
On my new site which implements ember-pouch, I encounter the issue that upon first load of page, an error occurs:
too much recursion vendor-f49700c71897d8185469b878fc3a8c2a.js:36
AbortError vendor-f49700c71897d8185469b878fc3a8c2a.js:35
Error: once called more than once vendor-f49700c71897d8185469b878fc3a8c2a.js:37
AbortError vendor-f49700c71897d8185469b878fc3a8c2a.js:35
Error: once called more than once vendor-f49700c71897d8185469b878fc3a8c2a.js:37
AbortError vendor-f49700c71897d8185469b878fc3a8c2a.js:35
Error: once called more than once vendor-f49700c71897d8185469b878fc3a8c2a.js:37
AbortError vendor-f49700c71897d8185469b878fc3a8c2a.js:35
Error: once called more than once vendor-f49700c71897d8185469b878fc3a8c2a.js:37
AbortError vendor-f49700c71897d8185469b878fc3a8c2a.js:35
Error: once called more than once vendor-f49700c71897d8185469b878fc3a8c2a.js:37
AbortError vendor-f49700c71897d8185469b878fc3a8c2a.js:35
Error: once called more than once vendor-f49700c71897d8185469b878fc3a8c2a.js:37
AbortError vendor-f49700c71897d8185469b878fc3a8c2a.js:35
Error: once called more than once vendor-f49700c71897d8185469b878fc3a8c2a.js:37
AbortError vendor-f49700c71897d8185469b878fc3a8c2a.js:35
Error: once called more than once vendor-f49700c71897d8185469b878fc3a8c2a.js:37
AbortError vendor-f49700c71897d8185469b878fc3a8c2a.js:35
Error: once called more than once vendor-f49700c71897d8185469b878fc3a8c2a.js:37
AbortError vendor-f49700c71897d8185469b878fc3a8c2a.js:35
Error: once called more than once vendor-f49700c71897d8185469b878fc3a8c2a.js:37
AbortError vendor-f49700c71897d8185469b878fc3a8c2a.js:35
Error: once called more than once vendor-f49700c71897d8185469b878fc3a8c2a.js:37
AbortError vendor-f49700c71897d8185469b878fc3a8c2a.js:35
Error: once called more than once vendor-f49700c71897d8185469b878fc3a8c2a.js:37
AbortError vendor-f49700c71897d8185469b878fc3a8c2a.js:35
Error: once called more than once vendor-f49700c71897d8185469b878fc3a8c2a.js:37
AbortError vendor-f49700c71897d8185469b878fc3a8c2a.js:35
Error: once called more than once vendor-f49700c71897d8185469b878fc3a8c2a.js:37
AbortError vendor-f49700c71897d8185469b878fc3a8c2a.js:35
Error: once called more than once vendor-f49700c71897d8185469b878fc3a8c2a.js:37
AbortError vendor-f49700c71897d8185469b878fc3a8c2a.js:35
Error: once called more than once vendor-f49700c71897d8185469b878fc3a8c2a.js:37
AbortError vendor-f49700c71897d8185469b878fc3a8c2a.js:35
TypeError: setting a property that has only a getter vendor-f49700c71897d8185469b878fc3a8c2a.js:36
uncaught exception: {"status":500,"name":"error","message":"AbortError"}
TypeError: setting a property that has only a getter
But on subsequent page loads, the data is correctly retrieved and stored in the client (in Chrome; in Firefox, the page never retrieves data).
Perhaps this is a pouch-db issue, but my first assumption is that this is something ember-related.
Hi,
I bumped into a small issue and I hope you guys can help me.
I’m writing an electron application with ember-cli and ember-pouch.
The scenario is as follows:
I have two routes: /trains
and /train/:train_id
When I boot the app from the /trains
route I get all the trains, which is good.
When I boot the app from the /train/:train_id
route I get that specific train, which is also good, but if I then transition into the /trains
route the findAll method of the store only returns that specific train that was already loaded.
Any ideas on this?
For the time being I can work around this issue by implementing:
shouldReloadAll: function () {
return true;
}
on the adapter, but this is not desired of course.
Thanks in advance!
As far as I can make out ember-pouch does not support attachments, is that correct? I saw that relational-pouch does support them, are there any plans to implement them in ember-pouch?
Starting in ember-data 1.0.0-beta16, adapters will no longer receive actual records. They will receive snapshots instead. See emberjs/data#2883.
This is a placeholder for any work that's necessary to adapt to this — it's possible that no changes will be necessary.
Good day all,
i try to implement authentication in ember-pouch which login & logout but i keep facing problem.
i know there is library named CouchDB Authentication but don't have any idea how to include in the ember project.
your help is highly appreciated
So right now there are automated Travis tests in relational-pouch, but I have no idea what the best practice is for an Ember/Broccoli/Ember Data plugin, so I've just punted.
Really there should be tests, though. It's kind of embarrassing that I have none.
I get this deprecation warning:
Ember Inspector (Deprecation Trace): The default behavior of shouldReloadAll will change in Ember Data 2.0 to always return false when there is at least one "author" record in the store. If you would like to preserve the current behavior please override shouldReloadAll in your adapter:application and return true.
Do we need to change something? Is the new behavior better?
I noticed that @taras'sember-pouchDB
library doesn't require you to add rev
properties to each model.
This is the code from his project that handles that: /lib/ember-pouchdb/storage.js.
(storage.js imports Model from /lib/ember-pouchdb/model.js which is the only other file referencing the rev
property)
I would imagine there's some good way to automatically handle adding the same string field to every model so a user doesn't have to do this. (and if there isn't a good way that maybe there should be some api added to ember or pouchdb)
Hi,
Im going to implement findQuery() in ember-pouch but the project I need to use it in is being built using ember-tools (which is based on commonJS) and the build process is complaining of missing include files which i cant find in the ember-pouch or relational-pouch repos.
e.g. Error: Cannot find module './reject'
Could anyone suggest the best way to include ember-pouch, relational-pouch and pouchdb in an ember-tools project?
cheers
Is switching between CouchDB and PouchDB at runtime possible with this adapter? I'd like to prompt the user and get permission before pulling their data into the browser.
If not, I might try to create another community CouchDB and/or PouchDB adapter, so any basic advice on how to structure this would be greatly appreciated: one adapter or two and which adapter/serializer to start with (extend)?
It seems that if the sync is not done ( at least the first one, when the DB is replicated ) ember pouch is not able to read the data.
Might be a bug with pouch-relational as I guess you need to hook inside some events for it to works.
Right now https://github.com/nolanlawson/ember-pouch/blob/master/lib/pouchdb-adapter.js#L10-L24 always runs. I have a different implementation of the change feed and have to modify the source. I'd like to add a flag/option somewhere to specify if this code should run or not.
The code I use for sync following does not reload all records, but tries to discover what happened and to only update what is necessary:
db.on 'change', (change) =>
return if change.id.match /^_design\//
db.setSchema [] unless db.rel # make sure relational pouch is triggered
{type, id} = db.rel.parseDocID change.id
console.log 'got change', type, id, change
record = @get('store').getById type, id # ask store for the record without loading it
if change.deleted
record.unloadRecord() if record?
else
#test if the record is known in the store
if record?
if record.get('isEmpty') || record.get('isLoading') || record.get('isSaving') || record.get('isReloading')
record.one 'didLoad', -> Ember.run.next ->
return if record.get 'isDestroyed'
try
console.log 'reload', record, 'after waiting for being loaded'
record.reload()
catch e
else
if change.changes[0].rev == record.get('rev')
return console.log 'no reload needed because we already have the correct rev (we triggered the change)', record
console.log 'will reload', type, id, 'because of server change'
record.reload()
else
#record is not known, but may be a match for a findAll
model = @get('store').modelFor type
typeMap = @get('store').typeMapFor model
return unless typeMap.findAllCache? # private property of Ember Data
console.log 'will load record', id, 'as a findAll on', type, 'exists'
return Ember.run.later =>
@get('store').find type, id
, 500
Sorry for the coffeescript, I hope it inspires others
I am working with an existing CouchDB dataset where records are structured like this:
{
"_id": "...",
"_rev": "...",
"my_attr": "value",
"my_other_attr": "value"
}
Ember pouch seems to want my data in this format:
{
"_id": "...",
"_rev": "...",
"data": {
"my_attr": "value",
"my_other_attr": "value"
}
}
Whilst I like this in principle it's not practical for me to migrate my CouchDB data as there are other clients which depend on the existing format. My question is, do you know of a good way which I can serialize and deserialize data between the two formats?
I'm wondering if there's somewhere I can get inbetween the replication from PouchDB to CouchDB and transform the data? Any help would be greatly appreciated!
@nolanlawson will be giving a talk on Web Workers on April 9th at Global Ember Meetup. Would you like to make it a double feature with an Introduction to ember-pouch
talk?
Introduction to
talks answer the following 3 questions:
After the talk, we'll edit the video and submit a PR with a link to the videos in the README. You can see some other Introduction to
talks here https://vimeo.com/album/3607049
What do you think?
TL;DR: How do I tell ember-pouch to delete the entire doc (not just the rev) with model.destroyRecord?
I have a simple setup with a list of friends with names. I create a new friend Mike
on Client A. It gets synced to Client B. Now I change the name of the friend to Peter
on Client B while being offline and parallel I change the name to Arnold
on Client A while being online. When Client B gets online again, we have a conflict, it makes sense. A winner will be selected, so far so good.
Now I want to delete this friend. But what happens? The friend does not disappear. The friend will get the name of the "loser" leaf instead. I read that this is intended.
But how do I tell ember/ember-pouch/pouch to delete the entire doc when I click destroyRecord within ember?
This has been introduced with ED 1.13, the PR can be found here: emberjs/data#3306. We should keep a proxy find
method for backwards compatibilty which just forwards to findRecord
. It's too late here for me to set up a PR, anyone who likes to jump in?
Got this request from a user, but I have no idea how to implement it.
I'm currently building a node-webkit application using Ember and Ember-Pouch. It works great to retrieve my model and to add data in the IndexedDB.
When it comes to querying though, I'm getting errors I'm not sure where it comes from.
- When I retrive the data, I call this.get('store').find('client'); in the route model. It gets all the records fine. However, if I add details, say this.get('store').find('client', { first_name: 'George' });, it always return an empty set even though George exists.
- When I want to query for a specific client from the controller, for instance this.get('store').find('client', { phone: phone_num });, it logs a GET app://cbt/clients?phone=5555555555 net::ERR_FILE_NOT_FOUND. Why is it searching for 'clients' plural while everywhere in my models it's 'client' singular?
I'm not very experienced with Ember-Data yet and I was wondering if my issues where with the Adapter or with Ember-Data.
Related to pouchdb-community/relational-pouch#3.
Hello! Thanks for your work on this, I’m happy that Ember Data and PouchDB are closer to working smoothly together.
I’m having trouble understanding how to create related models, which is maybe what #8 was about, but that person’s resolution was unclear to me.
I created a simple example application, which is running here.
Here are the models, representing issues of a magazine and the features within them:
DS.Model.extend({
title: DS.attr('string'),
features: DS.hasMany('feature'),
rev: DS.attr('string')
});
DS.Model.extend({
title: DS.attr('string'),
issue: DS.belongsTo('issue'),
rev: DS.attr('string')
});
Nothing special.
My question is: is it expected behaviour that an issue
is always stored in the database with features
as an empty array? When you visit the example application, you can see that it thinks, upon load, that the lone issue has 0 features. When you click the Load features
button, it runs store.find('feature')
, and suddenly the feature is connected to its parent issue.
There’s a button to print the contents of the PouchDB, here’s example output:
{
"total_rows": 2,
"offset": 0,
"rows": [
{
"id": "feature_2_4CDC71E9-08EC-2E42-B167-F4B3B495DBA4",
"key": "feature_2_4CDC71E9-08EC-2E42-B167-F4B3B495DBA4",
"value": {
"rev": "1-c9bd4bfcd6c416a54c5783ceaac787b1"
},
"doc": {
"data": {
"title": "A feature",
"issue": "A6A770A8-E416-CB0B-900A-58CF2809A369"
},
"_id": "feature_2_4CDC71E9-08EC-2E42-B167-F4B3B495DBA4",
"_rev": "1-c9bd4bfcd6c416a54c5783ceaac787b1"
}
},
{
"id": "issue_2_A6A770A8-E416-CB0B-900A-58CF2809A369",
"key": "issue_2_A6A770A8-E416-CB0B-900A-58CF2809A369",
"value": {
"rev": "2-c05d1fb71749477e6c695283b7bac761"
},
"doc": {
"data": {
"title": "An issue",
"features": []
},
"_id": "issue_2_A6A770A8-E416-CB0B-900A-58CF2809A369",
"_rev": "2-c05d1fb71749477e6c695283b7bac761"
}
}
]
}
Maybe I am constructing the models in the wrong way? In my real application, I’m constructing test models in acceptance tests. For the example application, I made an initialiser to do the same:
{
name: 'data-populator',
after: 'store',
initialize: function(container, application) {
application.deferReadiness();
var store = container.lookup('store:main');
var issues = store.find('issue');
issues.then(function() {
if (issues.get('length') == 0) {
var issue = store.createRecord('issue', {title: 'An issue'});
issue.save().then(function() {
var feature = store.createRecord('feature', {title: 'A feature'});
issue.get('features').pushObject(feature);
feature.save();
issue.save().then(function() {
application.advanceReadiness();
});
});
}
else {
application.advanceReadiness();
}
});
}
}
I’ve tried a variety of ways of constructing the models, like passing in the issue when creating a feature:
var feature = store.createRecord('feature', {issue: issue, title: 'A feature'});
and many other variations, but never have I seen the features
array be anything but empty in the database.
I’ve been using weird workarounds like pre-loading all features in the issues route, and similarly for other related models, but I suspect I’m just missing something.
Being banging my head against this problem, has it seems there is no good way to do that ( where to put a hook to get the conflict notification, and what to do ).
For the what to do part, it seems fairly simple using pouchdb documentation ( even if they are not using any sample of three way merging ) but I think a complete sample would be a good idea.
I try to override the save method inside my models, and use :
save() {
_super().then(
(result) => { return result },
(err) => { return this.handleConflicts() }
)
}
But when I arrive there, to get the conflicts for the document I need to re-generate the id format that relation pouch is using, and it seems a bit of a bad idea.
If anyone have some pointer to that, that would be super cool.
The change watcher calls reload
when a change is encountered for a record that is in ember-data's store cache. However, the change notifier in PouchDB notifies for all changes, including ones that originated in the ember app. Compare the rev of the change to the rev the store knows about and avoid reloading for those changes.
If you do:
You get an error "Error while processing route: posts.index Cannot set property 'id' of undefined TypeError: Cannot set property 'id' of undefined"
The error points to the obj.id line in your code:
function transformOutput(typeInfo, pouchDoc) {
var obj = pouchDoc.data;
obj.id = deserialize(pouchDoc._id);
obj.rev = pouchDoc._rev;
return obj;
}
If you run with "ember server" and not the "ember build" version the code works fine.
If you can find the time take a look.
On: https://github.com/broerse/ember-cli-blog/tree/master/app/adapters the live updating stopped working. If you now change something in one browser you don't see the change until you switch to an other route and back. I tested with ember-pouch 1.2.3 and 1.2.4 and ember-data beta15 & beta16 but snapshots don't seem to be the problem.
When I use a relationship in my model like:
import DS from "ember-data";
import { Model } from 'ember-pouch';
var Modelname = Model.extend({
name: DS.attr('string', {defaultValue: ""}),
pages: DS.hasMany('page', {async: true, serialize: true})
});
export default Modelname;
The code is borrowed from @broerse from where the discussion started. The problem seems to be introduced with verson 19.1 of ember-data as brianmbutler states in the original discussion.
The same exception pops up with DS.belongsTo
.
With help of the Chrome debugger I was able to find the culprit in the init method.
...
if (!Ember.get(type, 'attributes').has('rev')) {
...
https://github.com/nolanlawson/ember-pouch/blob/master/addon/adapters/pouch.js#L82
expects type to be a model object but gets a string when a relationship is defined inside your model.
Does ember-pouch deal with conflicts?
At the moment, if I update from one client then attempt to update from another, it just does nothing. No error message at all. I'm not really sure what's going on? Maybe you could point me in the right direction?
Hi,
I done some initial work in making the project in to a proper ember-cli addon. With some refactoring on the way (could not help myself :)).
https://github.com/tchak/ember-pouch/commit/d573a41226a81aa5148ec04d330193a33c2aebbf
Would you be interested in a PR ? Or do you prefer to keep your less opinionated project as is?
We can probably find some middle-ground. Like I can extract some changes in your project and then release ember-cli-pouch
wrapper relying on bower build from ember-pouch
. Let me know how you fill about it.
Can we do a minor version increment to reflect the code changes with the last two or so PRs? When I do a npm install ember-pouch
or ember install ember-pouch
I still get an old version of ember-pouch which is not identical to the GitHub repo. I guess npm caches the code and doesn't update it until the version number has been incremented. At least their website says "nolanlawson published 3 weeks ago": https://www.npmjs.com/package/ember-pouch
I may have this poorly configured, but here is an idea:
Using pouch-find I create an index (because it wasn't working without an index, thought this may help)
db.createIndex({
index: {
fields: ['startDate', 'endDate']
}
}).then(function (result) {
console.log(result)
}).catch(function (err) {
console.log(error)
});
Then in the controller for the route:
export default Ember.ArrayController.extend({
sortProperties: 'startDate',
filterBy: 'startDate'
});
What am I missing here?
Being able to use the ArrayController seems like it will be a nice alternative to trying to get pouch-find working with relational pouch, but it just doesn't seem to be working properly. All I need is your normal upcoming events list - startDate $gte this morning, sorted by startDate ascending, only showing items with a date (for now). If I wanted to be really messy I could use async sortBy and filterBy to mess with the controller model property.
How would you resolve this issue with ember data?
Hi,
We have a Java application which uses LightCouch API to put the data to CouchDB and on browser we use ember-pouch to get the data for viewing.
Our POJO looks like the following
class Blog extends Document {
String title;
Date date;
....
}
When saving the object using LightPouch, the source looks like the following
{
"_id": "post_2_46252996-35A1-E69E-8E1A-753031B32E4D",
"_rev": "1-0371b19fac2a94ab0c8bdf9bb263bdd8",
"title": "",
"date": "2015-08-25T16:36:05.522Z",
"excerpt": "",
"body": "",
"author": "A1D67CD4-984C-4B00-831E-1EC598321435"
}
I notice that ember-pouch (or more precisely relational-pouch) expects the data to be wrapped under data attribute like the following
{
"_id": "post_2_46252996-35A1-E69E-8E1A-753031B32E4D",
"_rev": "1-0371b19fac2a94ab0c8bdf9bb263bdd8",
"data": {
"title": "",
"date": "2015-08-25T16:36:05.522Z",
"excerpt": "",
"body": "",
"author": "A1D67CD4-984C-4B00-831E-1EC598321435"
}
}
This means ember-pouch is not compatible with any CouchDB or PouchDB application due to the relational-pouch layer. Am I right?
Is there any particular reason it is design in such a way?
What can I do to make ember-pouch put the data in the same way as LightCouch (without wrapped in data)?
Regards,
--Nick
Finding a document which does not exists leads to an Ember error.
When issuing a find('book', 'abc')
relational-pouch returns with {"books":[]}
when the abc
id is not existing. Ember Data chokes on this response, as the response is not null
, so it assumes the data is there. In the end it runs https://github.com/emberjs/data/blob/7db210f29a45d9d874f9f7f52455bcd56ac2320a/packages/ember-data/lib/serializers/rest_serializer.js#L266. As there is no data in the array, primaryRecord
will stay undefined and the app will halt.
Question here is, should Ember Data be able to handle an empty list response? Or should Relational Pouch not return an empty response (if it is against the spec)?
My solution was to extend the adapter (sorry coffeescript):
ApplicationAdapter = Adapter.extend
db: new PouchDB 'mydb'
find: (store, type, id) ->
@_super(store, type, id)
.then (payload) ->
for type, list of payload
delete payload[type] unless list?.length > 0
throw 'Not found' if Ember.keys(payload).length == 0
payload
The code above allows for a find-or-create statement for example in a Route:
IndexRoute = Ember.Route.extend
model: ->
store = @store
return store.find('opname', 1)
.catch (reason) ->
switch reason
when 'Not found'
record = store.recordForId 'opname', 1
record.loadedData() # see https://github.com/emberjs/data/issues/1523
record
else throw reason
Another thing which might be integrated in the ember-pouch driver is a set of official errors. Passing 'Not found' string as an error is not too future friendly
The current solution when not finding a record relies on parsing the Error.message
to find out which type+id failed to load. Parsing Errors is not a good practise.
My solution would be to introduce an EmberPouchError object, which has a documented api. Ember Data has something similar implemented for validation, see https://github.com/emberjs/data/blob/689b2fa05a1137303d7742faa0d74da2eb9abba5/packages/ember-data/lib/system/adapter.js#L7-L66.
This code would then be possible:
find(...).catch(function(err){
if (err instanceof EmberPouchError) {
switch (err.message) {
case 'Not found':
console.log('obj not found, type=', err.type, ' id=', err.id);
return something sane here;
}
}
throw err
})
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.