persistence-rails 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/.gitignore +17 -0
- data/Gemfile +4 -0
- data/README.md +36 -0
- data/Rakefile +2 -0
- data/lib/generators/persistence/install_generator.rb +22 -0
- data/lib/generators/persistence/templates/application.js +10 -0
- data/lib/persistence-rails.rb +1 -0
- data/lib/persistence/rails.rb +8 -0
- data/lib/persistence/rails/engine.rb +6 -0
- data/lib/persistence/rails/version.rb +5 -0
- data/persistence-rails.gemspec +17 -0
- data/vendor/assets/javascript/persistence.all.js +16 -0
- data/vendor/assets/javascript/persistence.core.js +2419 -0
- data/vendor/assets/javascript/persistence.jquery.js +103 -0
- data/vendor/assets/javascript/persistence.jquery.mobile.js +256 -0
- data/vendor/assets/javascript/persistence.js +5 -0
- data/vendor/assets/javascript/persistence.migrations.js +303 -0
- data/vendor/assets/javascript/persistence.pool.js +47 -0
- data/vendor/assets/javascript/persistence.search.js +293 -0
- data/vendor/assets/javascript/persistence.store.appengine.js +412 -0
- data/vendor/assets/javascript/persistence.store.config.js +29 -0
- data/vendor/assets/javascript/persistence.store.memory.js +239 -0
- data/vendor/assets/javascript/persistence.store.mysql.js +127 -0
- data/vendor/assets/javascript/persistence.store.sql.js +900 -0
- data/vendor/assets/javascript/persistence.store.sqlite.js +123 -0
- data/vendor/assets/javascript/persistence.store.sqlite3.js +124 -0
- data/vendor/assets/javascript/persistence.store.titanium.js +193 -0
- data/vendor/assets/javascript/persistence.store.websql.js +218 -0
- data/vendor/assets/javascript/persistence.sync.js +353 -0
- metadata +76 -0
| @@ -0,0 +1,353 @@ | |
| 1 | 
            +
            //= require persistence.core
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            /**
         | 
| 4 | 
            +
             * @license
         | 
| 5 | 
            +
             * Copyright (c) 2010 Zef Hemel <zef@zef.me>
         | 
| 6 | 
            +
             * 
         | 
| 7 | 
            +
             * Permission is hereby granted, free of charge, to any person
         | 
| 8 | 
            +
             * obtaining a copy of this software and associated documentation
         | 
| 9 | 
            +
             * files (the "Software"), to deal in the Software without
         | 
| 10 | 
            +
             * restriction, including without limitation the rights to use,
         | 
| 11 | 
            +
             * copy, modify, merge, publish, distribute, sublicense, and/or sell
         | 
| 12 | 
            +
             * copies of the Software, and to permit persons to whom the
         | 
| 13 | 
            +
             * Software is furnished to do so, subject to the following
         | 
| 14 | 
            +
             * conditions:
         | 
| 15 | 
            +
             * 
         | 
| 16 | 
            +
             * The above copyright notice and this permission notice shall be
         | 
| 17 | 
            +
             * included in all copies or substantial portions of the Software.
         | 
| 18 | 
            +
             * 
         | 
| 19 | 
            +
             * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
         | 
| 20 | 
            +
             * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
         | 
| 21 | 
            +
             * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
         | 
| 22 | 
            +
             * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
         | 
| 23 | 
            +
             * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
         | 
| 24 | 
            +
             * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
         | 
| 25 | 
            +
             * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
         | 
| 26 | 
            +
             * OTHER DEALINGS IN THE SOFTWARE.
         | 
| 27 | 
            +
             */
         | 
| 28 | 
            +
             | 
| 29 | 
            +
            if(!window.persistence) { // persistence.js not loaded!
         | 
| 30 | 
            +
              throw new Error("persistence.js should be loaded before persistence.sync.js");
         | 
| 31 | 
            +
            }
         | 
| 32 | 
            +
             | 
| 33 | 
            +
            persistence.sync = {};
         | 
| 34 | 
            +
             | 
| 35 | 
            +
            persistence.sync.getJSON = function(uri, callback, errorCallback) {
         | 
| 36 | 
            +
                var xmlHttp = new XMLHttpRequest();
         | 
| 37 | 
            +
                xmlHttp.open("GET", uri, true);
         | 
| 38 | 
            +
                xmlHttp.send();
         | 
| 39 | 
            +
                xmlHttp.onreadystatechange = function() {
         | 
| 40 | 
            +
                  if(xmlHttp.readyState==4) {
         | 
| 41 | 
            +
                    if(xmlHttp.status==200) {
         | 
| 42 | 
            +
                        callback(JSON.parse(xmlHttp.responseText));
         | 
| 43 | 
            +
                    } else if(typeof errorCallback === 'function') {
         | 
| 44 | 
            +
                        errorCallback(xmlHttp);
         | 
| 45 | 
            +
                    }
         | 
| 46 | 
            +
                  }
         | 
| 47 | 
            +
                };
         | 
| 48 | 
            +
            };
         | 
| 49 | 
            +
             | 
| 50 | 
            +
            persistence.sync.postJSON = function(uri, data, callback) {
         | 
| 51 | 
            +
                var xmlHttp = new XMLHttpRequest();
         | 
| 52 | 
            +
                xmlHttp.open("POST", uri, true);
         | 
| 53 | 
            +
                xmlHttp.setRequestHeader('Content-Type', 'application/json');
         | 
| 54 | 
            +
                xmlHttp.send(data);
         | 
| 55 | 
            +
                xmlHttp.onreadystatechange = function() {
         | 
| 56 | 
            +
                  if(xmlHttp.readyState==4 && xmlHttp.status==200) {
         | 
| 57 | 
            +
                    callback(JSON.parse(xmlHttp.responseText));
         | 
| 58 | 
            +
                  }
         | 
| 59 | 
            +
                };
         | 
| 60 | 
            +
            }; 
         | 
| 61 | 
            +
             | 
| 62 | 
            +
             | 
| 63 | 
            +
            (function() {
         | 
| 64 | 
            +
             | 
| 65 | 
            +
                var argspec = persistence.argspec;
         | 
| 66 | 
            +
             | 
| 67 | 
            +
                persistence.sync.Sync = persistence.define('_Sync', {
         | 
| 68 | 
            +
                    entity: "VARCHAR(255)",
         | 
| 69 | 
            +
                    localDate: "BIGINT",
         | 
| 70 | 
            +
                    serverDate: "BIGINT",
         | 
| 71 | 
            +
                    serverPushDate: "BIGINT"
         | 
| 72 | 
            +
                  });
         | 
| 73 | 
            +
             | 
| 74 | 
            +
                persistence.sync.RemovedObject = persistence.define('_SyncRemovedObject', {
         | 
| 75 | 
            +
                    entity: "VARCHAR(255)",
         | 
| 76 | 
            +
                    objectId: "VARCHAR(32)"
         | 
| 77 | 
            +
                  });
         | 
| 78 | 
            +
             | 
| 79 | 
            +
             | 
| 80 | 
            +
                function getEpoch(date) {
         | 
| 81 | 
            +
                  return date.getTime();
         | 
| 82 | 
            +
                }
         | 
| 83 | 
            +
             | 
| 84 | 
            +
                persistence.sync.preferLocalConflictHandler = function(conflicts, updatesToPush, callback) {
         | 
| 85 | 
            +
                  conflicts.forEach(function(conflict) {
         | 
| 86 | 
            +
                      var update = {id: conflict.local.id};
         | 
| 87 | 
            +
                      conflict.properties.forEach(function(p) {
         | 
| 88 | 
            +
                          update[p] = conflict.local._data[p];
         | 
| 89 | 
            +
                        });
         | 
| 90 | 
            +
                      updatesToPush.push(update);
         | 
| 91 | 
            +
                    });
         | 
| 92 | 
            +
                  callback();
         | 
| 93 | 
            +
                };
         | 
| 94 | 
            +
             | 
| 95 | 
            +
                persistence.sync.preferRemoteConflictHandler = function(conflicts, updatesToPush, callback) {
         | 
| 96 | 
            +
                  conflicts.forEach(function(conflict) {
         | 
| 97 | 
            +
                      conflict.properties.forEach(function(p) {
         | 
| 98 | 
            +
                          conflict.local[p] = conflict.remote[p];
         | 
| 99 | 
            +
                        });
         | 
| 100 | 
            +
                    });
         | 
| 101 | 
            +
                  persistence.flush(callback);
         | 
| 102 | 
            +
                };
         | 
| 103 | 
            +
             | 
| 104 | 
            +
                function encodeUrlObj(obj) {
         | 
| 105 | 
            +
                  var parts = [];
         | 
| 106 | 
            +
                  for(var k in obj) {
         | 
| 107 | 
            +
                    if(obj.hasOwnProperty(k)) {
         | 
| 108 | 
            +
                      parts.push(encodeURI(k)+"="+encodeURI(obj[k]));
         | 
| 109 | 
            +
                    }
         | 
| 110 | 
            +
                  }
         | 
| 111 | 
            +
                  return "?" + parts.join("&");
         | 
| 112 | 
            +
                }
         | 
| 113 | 
            +
             | 
| 114 | 
            +
                /**
         | 
| 115 | 
            +
                 * The main caching and updating function, would be nice to refactor this
         | 
| 116 | 
            +
                 */
         | 
| 117 | 
            +
                function cacheAndFindUpdates(session, Entity, objects, lastLocalSyncTime, lastServerPushTime, conflictCallback, callback) {
         | 
| 118 | 
            +
                  var ids = [];
         | 
| 119 | 
            +
                  var lookupTbl = {};
         | 
| 120 | 
            +
             | 
| 121 | 
            +
                  var conflicts = [];
         | 
| 122 | 
            +
                  var updatesToPush = [];
         | 
| 123 | 
            +
                  var meta = Entity.meta;
         | 
| 124 | 
            +
                  var fieldSpec = meta.fields; 
         | 
| 125 | 
            +
                  
         | 
| 126 | 
            +
                  var objectsToRemove = [];
         | 
| 127 | 
            +
             | 
| 128 | 
            +
                  objects.forEach(function(item) {
         | 
| 129 | 
            +
                      if(item._removed) { // special marker
         | 
| 130 | 
            +
                        objectsToRemove.push(item.id);
         | 
| 131 | 
            +
                      } else {
         | 
| 132 | 
            +
                        ids.push(item.id);
         | 
| 133 | 
            +
                        lookupTbl[item.id] = item;
         | 
| 134 | 
            +
                      }
         | 
| 135 | 
            +
                    });
         | 
| 136 | 
            +
                  // Step 1: Look at local versions of remotely updated entities
         | 
| 137 | 
            +
                  var existingItems = [], groupedIds = [];
         | 
| 138 | 
            +
                  for (var i=0,l=Math.floor((ids.length/100)+1);i<l;i++) {
         | 
| 139 | 
            +
                    groupedIds.push(ids.slice(i*100, i*100+100));
         | 
| 140 | 
            +
                  }
         | 
| 141 | 
            +
                  persistence.asyncForEach(groupedIds, function(idGroup, next) {
         | 
| 142 | 
            +
                    Entity.all(session).filter('id', 'in', idGroup).list(function(groupOfExistingItems) {
         | 
| 143 | 
            +
                      existingItems.concat(groupOfExistingItems);
         | 
| 144 | 
            +
                      next();
         | 
| 145 | 
            +
                    });
         | 
| 146 | 
            +
                  }, function() {
         | 
| 147 | 
            +
                      existingItems.forEach(function(localItem) {
         | 
| 148 | 
            +
                          var remoteItem = lookupTbl[localItem.id];
         | 
| 149 | 
            +
                          delete remoteItem.id;
         | 
| 150 | 
            +
                          delete lookupTbl[localItem.id];
         | 
| 151 | 
            +
             | 
| 152 | 
            +
                          var localChangedSinceSync = lastLocalSyncTime < localItem._lastChange;
         | 
| 153 | 
            +
                          var itemUpdatedFields = { id: localItem.id };
         | 
| 154 | 
            +
                          var itemUpdated = false;
         | 
| 155 | 
            +
                          var conflictingProperties = [];
         | 
| 156 | 
            +
                          for(var p in remoteItem) {
         | 
| 157 | 
            +
                            if(remoteItem.hasOwnProperty(p) && p !== '_lastChange') {
         | 
| 158 | 
            +
                              if(localItem._data[p] !== remoteItem[p]) {
         | 
| 159 | 
            +
                                if(localChangedSinceSync && remoteItem._lastChange === lastServerPushTime) { 
         | 
| 160 | 
            +
                                  // Unchanged at server, but changed locally
         | 
| 161 | 
            +
                                  itemUpdatedFields[p] = localItem._data[p];
         | 
| 162 | 
            +
                                  itemUpdated = true;
         | 
| 163 | 
            +
                                } else if(localChangedSinceSync) { // Conflict!
         | 
| 164 | 
            +
                                  conflictingProperties.push(p);
         | 
| 165 | 
            +
                                } else {
         | 
| 166 | 
            +
                                  localItem[p] = persistence.jsonToEntityVal(remoteItem[p], fieldSpec[p]);
         | 
| 167 | 
            +
                                }
         | 
| 168 | 
            +
                              }
         | 
| 169 | 
            +
                            } 
         | 
| 170 | 
            +
                          }
         | 
| 171 | 
            +
                          if(itemUpdated) {
         | 
| 172 | 
            +
                            updatesToPush.push(itemUpdatedFields);
         | 
| 173 | 
            +
                          }
         | 
| 174 | 
            +
                          if(conflictingProperties.length > 0) {
         | 
| 175 | 
            +
                            conflicts.push({local: localItem, remote: remoteItem, properties: conflictingProperties});
         | 
| 176 | 
            +
                          }
         | 
| 177 | 
            +
                        });
         | 
| 178 | 
            +
                      // Step 2: Remove all remotely removed objects
         | 
| 179 | 
            +
                      var groupedObjectsToRemove = [];
         | 
| 180 | 
            +
                      for (var i=0,l=Math.floor((objectsToRemove.length/100)+1);i<l;i++) {
         | 
| 181 | 
            +
                        groupedObjectsToRemove.push(objectsToRemove.slice(i*100, i*100+100));
         | 
| 182 | 
            +
                      }
         | 
| 183 | 
            +
                      persistence.asyncForEach(groupedObjectsToRemove, function(group, next) {
         | 
| 184 | 
            +
                        Entity.all(session).filter('id', 'in', group).destroyAll(next);
         | 
| 185 | 
            +
                      }, function() {
         | 
| 186 | 
            +
                          // Step 3: store new remote items locally
         | 
| 187 | 
            +
                          // NOTE: all that's left in lookupTbl is new, we deleted the existing items
         | 
| 188 | 
            +
                          for(var id in lookupTbl) {
         | 
| 189 | 
            +
                            if(lookupTbl.hasOwnProperty(id)) {
         | 
| 190 | 
            +
                              var remoteItem = lookupTbl[id];
         | 
| 191 | 
            +
                              delete remoteItem.id;
         | 
| 192 | 
            +
                              var localItem = new Entity(remoteItem);
         | 
| 193 | 
            +
                              localItem.id = id;
         | 
| 194 | 
            +
                              localItem._lastChange = getEpoch(new Date());
         | 
| 195 | 
            +
                              session.add(localItem);
         | 
| 196 | 
            +
                            }
         | 
| 197 | 
            +
                          }
         | 
| 198 | 
            +
                          // Step 4: Find local new/updated/removed items (not part of the remote change set)
         | 
| 199 | 
            +
                          Entity.all(session).filter("_lastChange", ">", lastLocalSyncTime).list(function(allNewItems) {
         | 
| 200 | 
            +
                              var newItems = [];
         | 
| 201 | 
            +
                              for (var i=0,l=allNewItems.length;i<l;i++) {
         | 
| 202 | 
            +
                                if (ids.indexOf(allNewItems[i].id)===-1) {
         | 
| 203 | 
            +
                                  newItems.push(allNewItems[i]);
         | 
| 204 | 
            +
                                }
         | 
| 205 | 
            +
                              }
         | 
| 206 | 
            +
                              console.log("New items: ", newItems);
         | 
| 207 | 
            +
                              newItems.forEach(function(newItem) {
         | 
| 208 | 
            +
                                  var update = { id: newItem.id };
         | 
| 209 | 
            +
                                  for(var p in fieldSpec) {
         | 
| 210 | 
            +
                                    if(fieldSpec.hasOwnProperty(p) && p != '_lastChange') {
         | 
| 211 | 
            +
                                      update[p] = persistence.entityValToJson(newItem._data[p], fieldSpec[p]);
         | 
| 212 | 
            +
                                    }
         | 
| 213 | 
            +
                                  }
         | 
| 214 | 
            +
                                  for(var p in meta.hasOne) {
         | 
| 215 | 
            +
                                    if(meta.hasOne.hasOwnProperty(p)) {
         | 
| 216 | 
            +
                                      update[p] = persistence.entityValToJson(newItem._data[p], fieldSpec[p]);
         | 
| 217 | 
            +
                                    }
         | 
| 218 | 
            +
                                  }
         | 
| 219 | 
            +
                                  updatesToPush.push(update);
         | 
| 220 | 
            +
                                });
         | 
| 221 | 
            +
                              var removedObjColl = persistence.sync.RemovedObject.all(session).filter("entity", "=", meta.name);
         | 
| 222 | 
            +
                              removedObjColl.list(function(objs) {
         | 
| 223 | 
            +
                                  objs.forEach(function(obj) {
         | 
| 224 | 
            +
                                      updatesToPush.push({id: obj.objectId, _removed: true});
         | 
| 225 | 
            +
                                    });
         | 
| 226 | 
            +
                                  function next() {
         | 
| 227 | 
            +
                                    removedObjColl.destroyAll(function() {
         | 
| 228 | 
            +
                                        callback(updatesToPush);
         | 
| 229 | 
            +
                                      });
         | 
| 230 | 
            +
                                  }
         | 
| 231 | 
            +
                                  if(conflicts.length > 0) {
         | 
| 232 | 
            +
                                    conflictCallback(conflicts, updatesToPush, next);
         | 
| 233 | 
            +
                                  } else {
         | 
| 234 | 
            +
                                    next();
         | 
| 235 | 
            +
                                  }
         | 
| 236 | 
            +
                                })
         | 
| 237 | 
            +
                            });
         | 
| 238 | 
            +
                        });
         | 
| 239 | 
            +
                    });
         | 
| 240 | 
            +
                }
         | 
| 241 | 
            +
             | 
| 242 | 
            +
                persistence.sync.serviceSync = function(session, uri, args, conflictCallback, callback) {
         | 
| 243 | 
            +
                  persistence.sync.Sync.findBy(session, 'service', uri, function(sync) {
         | 
| 244 | 
            +
                      var lastServerSyncTime = sync ? persistence.get(sync, 'serverDate') : 0;
         | 
| 245 | 
            +
                      var lastServerPushTime = sync ? persistence.get(sync, 'serverPushDate') : 0;
         | 
| 246 | 
            +
                      var lastLocalSyncTime = sync ? persistence.get(sync, 'localDate') : 0;
         | 
| 247 | 
            +
                      if(!sync) {
         | 
| 248 | 
            +
                        sync = new persistence.sync.Sync(session, {service: uri});
         | 
| 249 | 
            +
                        session.add(sync);
         | 
| 250 | 
            +
                      }
         | 
| 251 | 
            +
                      if(!args.since) args.since = lastServerSyncTime;
         | 
| 252 | 
            +
                      persistence.sync.getJSON(uri + encodeUrlObj(args), function(result) {
         | 
| 253 | 
            +
                          var allUpdates = [];
         | 
| 254 | 
            +
                          cacheAndFindUpdates(session, Entity, result.updates, lastLocalSyncTime, lastServerPushTime, conflictCallback, function(updatesToPush) {
         | 
| 255 | 
            +
                              persistence.sync.postJSON(uri, JSON.stringify(updatesToPush), function(pushData) {
         | 
| 256 | 
            +
                                  session.flush(function() {
         | 
| 257 | 
            +
                                      sync.localDate = getEpoch(new Date());
         | 
| 258 | 
            +
                                      sync.serverDate = result.now;
         | 
| 259 | 
            +
                                      sync.serverPushDate = pushData.now;
         | 
| 260 | 
            +
                                      session.flush(callback);
         | 
| 261 | 
            +
                                    });
         | 
| 262 | 
            +
                                });
         | 
| 263 | 
            +
                            });
         | 
| 264 | 
            +
                        });
         | 
| 265 | 
            +
                    });
         | 
| 266 | 
            +
                  session.flush(function() {
         | 
| 267 | 
            +
                      persistence.sync.getJSON(uri + encodeUrlObj(args), function(result) {
         | 
| 268 | 
            +
                        });
         | 
| 269 | 
            +
                    });
         | 
| 270 | 
            +
                };
         | 
| 271 | 
            +
                
         | 
| 272 | 
            +
             | 
| 273 | 
            +
                function synchronize(session, uri, Entity, conflictCallback, callback, errorCallback) {
         | 
| 274 | 
            +
                  persistence.sync.Sync.findBy(session, 'entity', Entity.meta.name, function(sync) {
         | 
| 275 | 
            +
                      var lastServerSyncTime = sync ? persistence.get(sync, 'serverDate') : 0;
         | 
| 276 | 
            +
                      var lastServerPushTime = sync ? persistence.get(sync, 'serverPushDate') : 0;
         | 
| 277 | 
            +
                      var lastLocalSyncTime = sync ? persistence.get(sync, 'localDate') : 0;
         | 
| 278 | 
            +
                      if(!sync) {
         | 
| 279 | 
            +
                        sync = new persistence.sync.Sync(session, {entity: Entity.meta.name});
         | 
| 280 | 
            +
                        session.add(sync);
         | 
| 281 | 
            +
                      }
         | 
| 282 | 
            +
                      persistence.sync.getJSON(uri + '?since=' + lastServerSyncTime, function(result) {
         | 
| 283 | 
            +
                          cacheAndFindUpdates(session, Entity, result.updates, lastLocalSyncTime, lastServerPushTime, conflictCallback, function(updatesToPush) {
         | 
| 284 | 
            +
                              persistence.sync.postJSON(uri, JSON.stringify(updatesToPush), function(pushData) {
         | 
| 285 | 
            +
                                  session.flush(function() {
         | 
| 286 | 
            +
                                      sync.localDate = getEpoch(new Date());
         | 
| 287 | 
            +
                                      sync.serverDate = result.now;
         | 
| 288 | 
            +
                                      sync.serverPushDate = pushData.now;
         | 
| 289 | 
            +
                                      session.flush(callback);
         | 
| 290 | 
            +
                                    });
         | 
| 291 | 
            +
                                });
         | 
| 292 | 
            +
                            });
         | 
| 293 | 
            +
                        },
         | 
| 294 | 
            +
                        errorCallback);
         | 
| 295 | 
            +
                    });
         | 
| 296 | 
            +
                }
         | 
| 297 | 
            +
             | 
| 298 | 
            +
                persistence.entityDecoratorHooks.push(function(Entity) {
         | 
| 299 | 
            +
                    /**
         | 
| 300 | 
            +
                     * Declares an entity to be tracked for changes
         | 
| 301 | 
            +
                     */
         | 
| 302 | 
            +
                    Entity.enableSync = function(uri) {
         | 
| 303 | 
            +
                      Entity.meta.enableSync = true;
         | 
| 304 | 
            +
                      Entity.meta.syncUri = uri;
         | 
| 305 | 
            +
                      Entity.meta.fields['_lastChange'] = 'BIGINT';
         | 
| 306 | 
            +
                    };
         | 
| 307 | 
            +
             | 
| 308 | 
            +
                    Entity.syncAll = function(session, uri, conflictCallback, callback, errorCallback) {
         | 
| 309 | 
            +
                      var args = argspec.getArgs(arguments, [
         | 
| 310 | 
            +
                          { name: 'session', optional: true, check: function(obj) { return obj && obj.flush; }, defaultValue: persistence },
         | 
| 311 | 
            +
                          { name: 'uri', optional: true, check: argspec.hasType('string'), defaultValue: this.meta.syncUri },
         | 
| 312 | 
            +
                          { name: 'conflictCallback', check: argspec.isCallback() },
         | 
| 313 | 
            +
                          { name: 'callback', check: argspec.isCallback() },
         | 
| 314 | 
            +
                          { name: 'errorCallback', optional: true, check: argspec.isCallback() },
         | 
| 315 | 
            +
                        ]);
         | 
| 316 | 
            +
                      synchronize(args.session, args.uri, this, args.conflictCallback, args.callback, args.errorCallback);
         | 
| 317 | 
            +
                    };
         | 
| 318 | 
            +
                  });
         | 
| 319 | 
            +
             | 
| 320 | 
            +
                /**
         | 
| 321 | 
            +
                 * Resets _lastChange property if the object has dirty project (i.e. the object has changed)
         | 
| 322 | 
            +
                 */
         | 
| 323 | 
            +
                persistence.flushHooks.push(function(session, tx, callback) {
         | 
| 324 | 
            +
                    var queries = [];
         | 
| 325 | 
            +
                    for (var id in session.getTrackedObjects()) {
         | 
| 326 | 
            +
                      if (session.getTrackedObjects().hasOwnProperty(id)) {
         | 
| 327 | 
            +
                        var obj = session.getTrackedObjects()[id];
         | 
| 328 | 
            +
                        var meta = persistence.getEntityMeta()[obj._type];
         | 
| 329 | 
            +
                        if(meta.enableSync) {
         | 
| 330 | 
            +
                          var isDirty = obj._new;
         | 
| 331 | 
            +
                          for ( var p in obj._dirtyProperties) {
         | 
| 332 | 
            +
                            if (obj._dirtyProperties.hasOwnProperty(p)) {
         | 
| 333 | 
            +
                              isDirty = true;
         | 
| 334 | 
            +
                            }
         | 
| 335 | 
            +
                          }
         | 
| 336 | 
            +
                          if(isDirty) {
         | 
| 337 | 
            +
                            obj._lastChange = getEpoch(new Date());
         | 
| 338 | 
            +
                          }
         | 
| 339 | 
            +
                        }
         | 
| 340 | 
            +
                      }
         | 
| 341 | 
            +
                    }
         | 
| 342 | 
            +
                    session.objectsRemoved.forEach(function(rec) {
         | 
| 343 | 
            +
                        var meta = session.getMeta(rec.entity);
         | 
| 344 | 
            +
                        if(meta.enableSync) {
         | 
| 345 | 
            +
                          session.add(new persistence.sync.RemovedObject({entity: rec.entity, objectId: rec.id}));
         | 
| 346 | 
            +
                        }
         | 
| 347 | 
            +
                      });
         | 
| 348 | 
            +
                    session.objectsRemoved=[];
         | 
| 349 | 
            +
                    callback();
         | 
| 350 | 
            +
                  });
         | 
| 351 | 
            +
             | 
| 352 | 
            +
              }());
         | 
| 353 | 
            +
             | 
    
        metadata
    ADDED
    
    | @@ -0,0 +1,76 @@ | |
| 1 | 
            +
            --- !ruby/object:Gem::Specification
         | 
| 2 | 
            +
            name: persistence-rails
         | 
| 3 | 
            +
            version: !ruby/object:Gem::Version
         | 
| 4 | 
            +
              version: 0.0.1
         | 
| 5 | 
            +
              prerelease: 
         | 
| 6 | 
            +
            platform: ruby
         | 
| 7 | 
            +
            authors:
         | 
| 8 | 
            +
            - Alessandro Mencarini
         | 
| 9 | 
            +
            autorequire: 
         | 
| 10 | 
            +
            bindir: bin
         | 
| 11 | 
            +
            cert_chain: []
         | 
| 12 | 
            +
            date: 2012-10-05 00:00:00.000000000 Z
         | 
| 13 | 
            +
            dependencies: []
         | 
| 14 | 
            +
            description: Rails integration for Persistence.js
         | 
| 15 | 
            +
            email:
         | 
| 16 | 
            +
            - a.mencarini@freegoweb.it
         | 
| 17 | 
            +
            executables: []
         | 
| 18 | 
            +
            extensions: []
         | 
| 19 | 
            +
            extra_rdoc_files: []
         | 
| 20 | 
            +
            files:
         | 
| 21 | 
            +
            - .gitignore
         | 
| 22 | 
            +
            - Gemfile
         | 
| 23 | 
            +
            - README.md
         | 
| 24 | 
            +
            - Rakefile
         | 
| 25 | 
            +
            - lib/generators/persistence/install_generator.rb
         | 
| 26 | 
            +
            - lib/generators/persistence/templates/application.js
         | 
| 27 | 
            +
            - lib/persistence-rails.rb
         | 
| 28 | 
            +
            - lib/persistence/rails.rb
         | 
| 29 | 
            +
            - lib/persistence/rails/engine.rb
         | 
| 30 | 
            +
            - lib/persistence/rails/version.rb
         | 
| 31 | 
            +
            - persistence-rails.gemspec
         | 
| 32 | 
            +
            - vendor/assets/javascript/persistence.all.js
         | 
| 33 | 
            +
            - vendor/assets/javascript/persistence.core.js
         | 
| 34 | 
            +
            - vendor/assets/javascript/persistence.jquery.js
         | 
| 35 | 
            +
            - vendor/assets/javascript/persistence.jquery.mobile.js
         | 
| 36 | 
            +
            - vendor/assets/javascript/persistence.js
         | 
| 37 | 
            +
            - vendor/assets/javascript/persistence.migrations.js
         | 
| 38 | 
            +
            - vendor/assets/javascript/persistence.pool.js
         | 
| 39 | 
            +
            - vendor/assets/javascript/persistence.search.js
         | 
| 40 | 
            +
            - vendor/assets/javascript/persistence.store.appengine.js
         | 
| 41 | 
            +
            - vendor/assets/javascript/persistence.store.config.js
         | 
| 42 | 
            +
            - vendor/assets/javascript/persistence.store.memory.js
         | 
| 43 | 
            +
            - vendor/assets/javascript/persistence.store.mysql.js
         | 
| 44 | 
            +
            - vendor/assets/javascript/persistence.store.sql.js
         | 
| 45 | 
            +
            - vendor/assets/javascript/persistence.store.sqlite.js
         | 
| 46 | 
            +
            - vendor/assets/javascript/persistence.store.sqlite3.js
         | 
| 47 | 
            +
            - vendor/assets/javascript/persistence.store.titanium.js
         | 
| 48 | 
            +
            - vendor/assets/javascript/persistence.store.websql.js
         | 
| 49 | 
            +
            - vendor/assets/javascript/persistence.sync.js
         | 
| 50 | 
            +
            homepage: ''
         | 
| 51 | 
            +
            licenses: []
         | 
| 52 | 
            +
            post_install_message: 
         | 
| 53 | 
            +
            rdoc_options: []
         | 
| 54 | 
            +
            require_paths:
         | 
| 55 | 
            +
            - lib
         | 
| 56 | 
            +
            required_ruby_version: !ruby/object:Gem::Requirement
         | 
| 57 | 
            +
              none: false
         | 
| 58 | 
            +
              requirements:
         | 
| 59 | 
            +
              - - ! '>='
         | 
| 60 | 
            +
                - !ruby/object:Gem::Version
         | 
| 61 | 
            +
                  version: '0'
         | 
| 62 | 
            +
            required_rubygems_version: !ruby/object:Gem::Requirement
         | 
| 63 | 
            +
              none: false
         | 
| 64 | 
            +
              requirements:
         | 
| 65 | 
            +
              - - ! '>='
         | 
| 66 | 
            +
                - !ruby/object:Gem::Version
         | 
| 67 | 
            +
                  version: '0'
         | 
| 68 | 
            +
            requirements: []
         | 
| 69 | 
            +
            rubyforge_project: 
         | 
| 70 | 
            +
            rubygems_version: 1.8.17
         | 
| 71 | 
            +
            signing_key: 
         | 
| 72 | 
            +
            specification_version: 3
         | 
| 73 | 
            +
            summary: persistence-rails integrates client-side database ORM Persistence.js with
         | 
| 74 | 
            +
              Rails 3.1 asset pipeline
         | 
| 75 | 
            +
            test_files: []
         | 
| 76 | 
            +
            has_rdoc: 
         |