I've created a Lawnchair store and saved it. See the following code:
var DB = new Lawnchair({ name: "DB", adapter: ["indexed-db", "webkit-sqlite", "ie-userdata", "blackberry-persistent-store", "dom", "window-name", "gears-sqlite", "memory"] });
DB.save({ key: "resKey", res: res});
Here res is a javascript object, it is the data that gets stored.
But when I close and reopen the web page the next time, I want to check whether this store exists. If the store exists, I want to check whether this document exists. How to do these checks?
Thanks
PS - Is there any good resource where I can learn Lawnchair?
Finally after a lot of trials, I came up with the following :
// create a store //* CORRECT TO USE
DB = new Lawnchair({ name: "DB", adapter: ["indexed-db", "webkit-sqlite", "ie-userdata", "blackberry-persistent-store", "dom", "window-name", "gears-sqlite", "memory"] });
//Save a document/table
DB.save({ key: "resKey", data: res }, function () {
//Access the created store
DB = Lawnchair({ name: "DB", adapter: ["indexed-db", "webkit-sqlite", "ie-userdata", "gears-sqlite", "blackberry-persistent-store", "dom", "window-name", "memory"] });
console.log(DB)
//check if the document exists based on the key we used to create it
DB.exists("resKey", function (e) {
console.log("exists : " + e)
if (e == true) {
//get all records from the store
DB.all(function (r) {
console.log(r);
//remove all document/table from the store
DB.nuke(function () {
console.log("Data nuke-ed");
//check if the document exists based on the key we used to create it
DB.exists("resKey", function (e) {
console.log("exists : " + e)
if (e == true) {
//get all records from the store
DB.all(function (r) {
console.log(r);
});
} else {
console.log("Data deleted");
}
});
});
});
} else {
}
});
});
Please let me know if this is the right way to do it or is there a better way. If you liked my effort give me points :)
Related
I work over a small React app that should store some data in local storage. And if I understand it correctly, it should keep them till clearly ordered to clear. The reason for this post is that while app data perfectly survives the refreshing page action, it disappears after closing/opening Chrome.
Here is the function which creates the storage:
export function initGlobalStorage() {
var Storage = function (options) {
options = options || {};
for (var i in options) {
this[i] = options[i];
}
};
const prefix = window.location.href;
Storage.prototype = {
storage: window.localStorage,
addPrefix: function(key){return (prefix + key); },
set: function (key, value) {
this.storage.setItem(this.addPrefix(key), JSON.stringify(value));
},
get: function (key) {
return this.storage.getItem(this.addPrefix(key));
},
remove: function (key, value) {
this.storage.remove(key, value);
},
clear: function () {
this.storage.clear();
},
key: function (index) {
return this.storage.key(index);
},
each: function (fn) {
if (typeof fn === "function") {
for (var i = 0, key; i < this.storage.length; ++i) {
key = this.storage.key(i);
fn(this.storage.getItem(key), key, i);
}
}
},
getAll:function(){
let result =[];
for(var key in this.storage){
if (key.includes(prefix)){result.push(JSON.parse(this.storage.getItem(key)))};
}
return result;
},
hasItems:function(){
console.log(this.getAll().length);
return this.getAll().length? true:false;
},
};
window.Storage = {
local: new Storage({ storage: window.localStorage }),
session: new Storage({ storage: window.sessionStorage }),
};
};
window.local.href is for distinguish 'my items' in localStorage from others that possibly exists there on client computer. BTW, currently I only test this app on localhost.
Here is how above function is applied
export function checkSupportForCache() {
return dispatch => {
if (storageAvailable('localStorage')) {
dispatch(cacheSupported());
console.warn("Storage available");
initGlobalStorage();
if (window.Storage.local.hasItems()){
console.log('Storage contains items');
dispatch(cacheNotEmpty());
}else{
console.warn("No items in storage");
}
} else {
console.warn("Storage not available");
}
};
}
storageAvailable('localStorage') is a function that checks support for localStorage in a certain browser.
As I have written, when I refresh page localStorage is still there - then I suppose code is OK.
But what happens when do close browser then? I do not consciously request for any sort of purging action. Do I unconsciously? I have checked Chrome settings and there is nothing that looks suspicious. Do I not understand anything at all as per subject? Maybe, just give me a hint.
I have a model "User" that has a Many-to-One relationship with a "Subject".
User.js
attributes: {
subject: { model: 'subject' },
}
Subject.js
attributes: {
name: { type: 'string', unique: true, required: true },
}
When I call the blueprint create function for a User "/user" and pass in the data:
{
"name":"Test",
"subject":{"name":"Do Not Allow"}
}
It creates the user and also creates the Subject. However I do not want to allow the subject to be created, I only want to be able to attach an existing one. For example I would like it to reject the subject being created using the above data but allow the subject to be attached by using the below data.
{
"name":"Test",
"subject":1
}
I tried adding a policy (shown below) but this only stops the subject from being created using the URL "/subject" and not the nested create shown above.
'SubjectController':{
'create':false
}
Edit
To help understand what is going on here this is the lifecycle process it is going through:
Before Validation of Subject
After Validation of Subject
Before Creating Subject
After Creating Subject
Before Validation of User
After Validation of User
Before Creating User
Before Validation of User
After Validation of User
After Creating User
As you can see it is validating and creating the subject before it even gets to validating or creating the user.
You want to avoid the creation of an associated object when calling the blueprint creation route.
Create a policy (I've named it checkSubjectAndHydrate) and add it into the policies.js file:
// checkSubjectAndHydrate.js
module.exports = function (req, res, next) {
// We can create a user without a subject
if (_.isUndefined(req.body.subject)) {
return next();
}
// Check that the subject exists
Subject
.findOne(req.body.subject)
.exec(function (err, subject) {
if (err) return next(err);
// The subject does not exist, send an error message
if (!subject) return res.forbidden('You are not allowed to do that');
// The subject does exist, replace the body param with its id
req.body.subject = subject.id;
return next();
});
};
// policies.js
module.exports.policies = {
UserController: {
create: 'checkSubjectAndHydrate',
update: 'checkSubjectAndHydrate',
}
};
You should be passing the subject id (e.g. 1) instead of an object (e.g. { name: 'Hello, World!' }) containing the name of the subject as it's not necessarily unique.
If it is unique, you should replace the object by its id inside a beforeValidate for example.
// User.js
module.exports = {
...
beforeValidate: function (users, callback) {
// users = [{
// "name":"Test",
// "subject":{"name":"Do Not Allow"}
// }]
async.each(users, function replaceSubject(user, next) {
var where = {};
if (_.isObject(user.subject) && _.isString(user.subject.name)) {
where.name = user.subject.name;
} else if(_.isInteger(user.subject)) {
where.id = user.subject;
} else {
return next();
}
// Check the existence of the subject
Subject
.findOne(where)
.exec(function (err, subject) {
if (err) return next(err);
// Create a user without a subject if it does not exist
user.subject = subject? subject.id : null;
next();
});
}, callback);
// users = [{
// "name":"Test",
// "subject":1
// }]
}
};
You can create custom type for subject, and add your logic inside model. I'm not 100% sure I understood the attach sometimes part but maybe this could help:
models/User.js
module.exports = {
schema: true,
attributes: {
name: {
type: 'string'
},
subject: {
type: 'json',
myValidation: true
}
},
types: {
myValidation: function(value) {
// add here any kind of logic...
// for example... reject if someone passed name key
return !value.name;
}
}
};
You can find more info here http://sailsjs.org/documentation/concepts/models-and-orm/validations at the bottom of the page.
If I totally missed the point... The second option would be to add beforeCreate and beforeUpdate lifecycle callback to your model like this:
models/User.js
module.exports = {
schema: true,
attributes: {
name: {
type: 'string'
},
subject: {
type: 'json'
}
},
beforeCreate: function (values, cb) {
// for example... reject creating of subject if anything else then value of 1
if (values.subject && values.subject !== 1) return cb('make error obj...');
cb();
},
beforeUpdate: function (values, cb) {
// here you can add any kind of logic to check existing user or current update values that are going to be updated
// and allow it or not
return cb();
}
};
By using this you can use one logic for creating and another one for updating... etc...
You can find more info here: http://sailsjs.org/documentation/concepts/models-and-orm/lifecycle-callbacks
EDIT
Realized you have trouble with relation, and in above examples I thought you are handling type json...
module.exports = {
schema: true,
attributes: {
name: {
type: 'string'
},
subject: {
model: 'subject'
}
},
beforeValidate: function (values, cb) {
// subject is not sent at all, so we just go to next lifecycle
if (!values.subject) return cb();
// before we update or create... we will check if subject by id exists...
Subject.findOne(values.subject).exec(function (err, subject) {
// subject is not existing, return an error
if (err || !subject) return cb(err || 'no subject');
//
// you can also remove subject key instead of sending error like this:
// delete values.subject;
//
// subject is existing... continue with update
cb();
});
}
};
I'm trying to exclude documents to show on client based on user event.
this is my attempt which failed:
Template.documents.events({
'click #dontShowThisDocument': function () {
Session.set('excludedDocument', this._id);
}
});
Template.documents.helpers({
lists: function () {
var excludedDocuments = [];
excludedDocuments.push(Session.get('excludedDocument'));
return Coll.find({_id:{$nin:excludedDocuments});
}
});
how to create array session storage with meteor so then the user able to exclude certain document on a list reactively ?
Thank You so much.
A Session variable can hold an array (or any object really) which means you could do this:
Template.documents.events({
'click #dontShowThisDocument': function () {
var excluded = Session.get('excludedDocument');
if ( excluded ) excluded.push(this._id);
else excluded = [ this.id ];
Session.set('excludedDocument',excluded);
}
});
Template.documents.helpers({
lists: function () {
return Coll.find({ _id: { $nin: Session.get('excludedDocument') });
}
});
I have Firebase entries in /items with the properties title and points. I am trying to check to see if an item of the same title exists before entering a new one.
This is what I have but it does not happen:
app.controller('ItemController', function($scope, FURL, $firebase, $location, toaster) {
var ref = new Firebase(FURL);
var fbItems = $firebase(ref.child('items')).$asArray();
$scope.addItem = function(item) {
// var iItem = $scope.item.title;
var userId = $scope.item.title;
checkIfUserExists(userId);
};
function userExistsCallback(userId, exists) {
if (exists) {
alert('user ' + userId + ' exists!');
} else {
alert('user ' + userId + ' does not exist!');
}
}
function checkIfUserExists(userId) {
ref.child('items').once('value', function(snapshot) {
var exists = (snapshot.val() !== null);
userExistsCallback(userId, exists);
});
}
});
The Realtime Database is a key/value JSON database. This means that if you store a title name as a key, it will be super quick to look it up.
Take the following data for example.
{
"items": {
"title-1": {
"something": "foo"
},
"title-2": {
"something": "baz"
}
}
}
Now let's say we want to check to see if title-2 exists. We can do this with an easy read.
function checkForTitle(title, cb) {
var itemsRef = new Firebase('<my-firebase-app>/items');
var titleRef = itemRef.chld(title).once('value', function(snap) {
cb(snap.exists());
});
}
checkForTitle('title-2', function(doesExist) {
console.log(doesExist); // true
});
To make sure the check happens on the server, you can write a Security Rule for it. Or, better yet use the new Bolt Compiler.
{
"items": {
"$item": {
".write": "!data.exists()" // don't overwrite existing data
}
}
}
You should upgrade your AngularFire version. I noticed you're using $firebase().$asArray which means you're on the 0.9 version of AngularFire, which is unsupported. Look into upgrading to the 1.0+ version which is officially support by Firebase.
var urlSchema = new Schema ( {
url : String,
visitor : [{name: String,date: Date}],
counter : Number
});
var url = mongoose.model('url',urlSchema);
var domain = blah blah;
var conditions = { url: domain };
var update = { $inc : {counter:1},
$push : { visitor: [{
name: data.username,
date: new Date()
}]
}
};
var options = {upsert: true};
url.update(conditions,update,options,function(err){
if(err){
console.log(err);
}else{
console.log('A domain successfully added to DB');
}
Currently I am using the schema and code above to make an access counter for each page.
It upserts url documents which is counting total access and holding access user info.
so far so good It's working properly.
now I want to add "counter : Number" in visitor array and when the event occurs, if the user is already in visitor array,I want to update that instead of pushing new one.
But I have no idea how to make the 'double upsert' command.
is there anyway to do that?
It may be a bit difficult even impossible perform a query that satisfy your condition. I have reproduced your scenario with following query
url.findOne({'url': 'search.php', 'visitor.name': "JohnDoe"},
function (err, visitor) {
if (visitor) {
url.update(
{
'url': 'search.php', 'visitor.name': "JohnDoe"
},
{
$inc: {'visitor.$.counter': 1, 'counter': 1}
},
function(err, result) {
if (err) {
console.log("Error occured")
} else {
console.log("Success");
}
});
} else {
var conditions = { url: 'search.php' };
var update = { $inc : {counter:1},
$push : { visitor: [{
name: data.username,
date: new Date(),
counter: 0
}]
}
};
var options = {upsert: true};
url.update(conditions,update,options,function(err){
if(err){
console.log(err);
}else{
console.log('A domain successfully added to DB');
}
});
}
}
);
Simple, insert if not exists with counter = 0, update if exists with incrementing counter by 1