I am having some issues getting Backbone to save multiple layers of collections. I have the following models:
var Question = Backbone.Model.extend({
urlRoot: "/question"
});
var QuestionList = Backbone.Collection.extend({
model: Question,
url: "/question",
parse: function(response) {
return response.objects;
}
});
var QuestionBank = Backbone.Model.extend({
urlRoot: "/questionbank"
});
var QuestionBankList = Backbone.Collection.extend({
model:QuestionBank,
url: "/questionbank",
parse: function(response) {
return response.objects;
}
});
var Answer = Backbone.Model.extend({
urlRoot: "/answer"
})
var AnswerList = Backbone.Collection.extend({
model: Answer,
url: "/answer",
parse: function(response) {
return response.objects;
}
});
A questionbank has many questions, and a question has many answers.
When I save my collection the model is correct, but the JSON that is sent out does not include the second level of collection (the answers):
{"active_question_bank": true, "id":
"51a8c5d72ace7a458fd0d000", "question_bank_name": "New Q", "questions":
[{"active_question": true, "answers": [], "difficulty": null,
"id": "51a8d1be2ace7a458fd0d008", "question": "What is your favorite Color?",
"question_is_and_type": false, "question_type": 1, "resource_uri":
"/question/51a8d1be2ace7a458fd0d008", "tags": [""]}], "resource_uri":
"/questionbank/51a8c5d72ace7a458fd0d000"}
In particular it sends a blank "answers": [] every time. I'm relatively new to backbone, so perhaps this is an impossible task, but the concept seems fairly trivial.
Try defining the models and collections in the following pattern and then check the JSON being sent to the server.
var Answer = Backbone.Model.extend({
urlRoot: "/answer",
});
var AnswerCollection = Backbone.Collection.extend({
model: Answer,
urlRoot: "/answer",
});
// a question can contain many answers which can be accessed via AnswerList
var Question = Backbone.Model.extend({
urlRoot: "/question",
defaults: {
AnswerList: new AnswerCollection(),
},
parse: function(response) {
response.AnswerList= new AnswerCollection(response.AnswerList);
return response;
}
});
var QuestionCollection = Backbone.Collection.extend({
model: Question,
url: "/question",
});
// question-bank contains many questions which can be accessed via QuestionList
var QuestionBank = Backbone.Model.extend({
urlRoot: "/questionbank",
defaults: {
QuestionList: new QuestionCollection(),
},
parse: function(response) {
response.QuestionList = new QuestionCollection(response.QuestionList);
return response;
}
});
Related
I use update Query for push some data in array in Mongodb and I use mongoose in nodeJs.Pplease anyone can help out from this.
Model Schema :
var mongoose = require('mongoose')
var Schema = mongoose.Schema;
var bcrypt = require('bcrypt')
var schema = new Schema({
email: { type: String, require: true },
username: { type: String, require: true },
password: { type: String, require: true },
creation_dt: { type: String, require: true },
tasks : []
});
module.exports = mongoose.model('User',schema)
So I use this schema and I want to push data in tasks array and here is my route code for pushing data.
Route For Update Data in Tasks:
router.post("/newTask", isValidUser, (req, res) => {
addToDataBase(req, res);
});
async function addToDataBase(req, res) {
var dataa = {
pName: req.body.pName,
pTitle: req.body.pTitle,
pStartTime: req.body.pStartTime,
pEndTime: req.body.pEndTime,
pSessionTime: req.body.pSessionTime,
};
var usr = new User(req.user);
usr.update({ email: req.user.email }, { $push: { tasks: dataa } });
console.log(req.user.email);
try {
doc = await usr.save();
return res.status(201).json(doc);
} catch (err) {
return res.status(501).json(err);
}
}
Here I create a async function and call that function in route but when I post data using postman it response with status code 200(success) but it updates nothing in my database.
Output screenshot:
as you can see in this image task : [].. it updates nothing in that array but status is success
I don't know why is this happening.
You can achieve this task easier using findOneAndUpdate method.
router.put("/users", isValidUser, async (req, res) => {
var data = {
pName: req.body.pName,
pTitle: req.body.pTitle,
pStartTime: req.body.pStartTime,
pEndTime: req.body.pEndTime,
pSessionTime: req.body.pSessionTime,
};
try {
const user = await User.findOneAndUpdate(
{ email: req.user.email },
{
$push: {
tasks: data,
},
},
{ new: true }
);
if (!user) {
return res.status(404).send("User with email not found");
}
res.send(user);
} catch (err) {
console.log(err);
res.status(500).send("Something went wrong");
}
});
Also I strongly suggest using raw / JSON data for request body, that's how most ui libraries (reactjs, angular) send data.
To be able to parse json data, you need to add the following line to your main file before using routes.
app.use(express.json());
TEST
Existing user:
{
"tasks": [],
"_id": "5e8b349dc285884b64b6b167",
"email": "test#gmail.com",
"username": "Kirtan",
"password": "123213",
"creation_dt": "2020-04-06T14:21:40",
"__v": 0
}
Request body:
{
"pName": "pName 1",
"pTitle": "pTitle 1",
"pStartTime": "pStartTime 1",
"pEndTime": "pEndTime 1",
"pSessionTime": "pSessionTime 1"
}
Response:
{
"tasks": [
{
"pName": "pName 1",
"pTitle": "pTitle 1",
"pStartTime": "pStartTime 1",
"pEndTime": "pEndTime 1",
"pSessionTime": "pSessionTime 1"
}
],
"_id": "5e8b349dc285884b64b6b167",
"email": "test#gmail.com",
"username": "Kirtan",
"password": "123213",
"creation_dt": "2020-04-06T14:21:40",
"__v": 0
}
Also as a side note, you had better to create unique indexes on username and email fields. This can be done applying unique: true option in the schema, but better to create these unique indexes at mongodb shell like this:
db.users.createIndex( { "email": 1 }, { unique: true } );
db.users.createIndex( { "username": 1 }, { unique: true } );
It's been awhile since I've done mongoose, but I'm pretty sure <model>.update() also actively updates the record in Mongo.
You use .update() when you want to update an existing record in Mongo, but you are instantiating a new User model (i.e. creating a new user)
try the following code instead for a NEW USER:
router.post('/newTask', isValidUser, (req, res) => {
addToDataBase(req,res)
})
async function addToDataBase(req, res) {
var dataa = {
pName: req.body.pName,
pTitle: req.body.pTitle,
pStartTime: req.body.pStartTime,
pEndTime: req.body.pEndTime,
pSessionTime: req.body.pSessionTime
}
// email field is already in `req.user`
var usr = new User({ ...req.user, tasks: [dataa] });
console.log(req.user.email);
try {
await usr.save();
return res.status(201).json(doc);
}
catch (err) {
return res.status(501).json(err);
}
}
Now, if you wanted to update an existing record :
router.post('/newTask', isValidUser, (req, res) => {
addToDataBase(req,res)
})
async function addToDataBase(req, res) {
var dataa = {
pName: req.body.pName,
pTitle: req.body.pTitle,
pStartTime: req.body.pStartTime,
pEndTime: req.body.pEndTime,
pSessionTime: req.body.pSessionTime
}
try {
await usr. updateOne({ email : req.user.email}, { $push: { tasks: dataa } });
return res.status(201).json(doc);
}
catch (err) {
return res.status(501).json(err);
}
}
For more info read: https://mongoosejs.com/docs/documents.html
I have two controllers/models in my Sails project which is Clubs and Members. One club can have many members.
I try to put the id of 'Clubs' as a reference id (like a foreign key) in 'Members', so that I can retrieve the members of a club by using the reference id in 'Members'. I want to display the members according to their clubs at the homepage. However I could not find a way to pass the id value of 'Clubs' to the 'Members' controller. Below are some of the codes:
Clubs.js
module.exports = {
attributes: {
clubName: {
type: 'string',
},
clubDesc: {
type: 'string',
},
},
};
Members.js
module.exports = {
attributes: {
memberName: {
type: 'string',
},
clubId: {
type: 'string',
},
},
};
ClubsController.js
module.exports = {
list: function(req, res) {
Clubs.find({}).exec(function(err, club) {
if(err) {
res.send(500, {error: 'Database Error'});
}
res.view('pages/club-list', {clubs:club});
});
},
add: function(req, res) {
res.view('pages/club-add');
},
create: function(req, res) {
var clubName = req.body.clubName;
var clubDesc = req.body.clubDesc;
Clubs.create({clubName:clubName, clubDesc:clubDesc}).exec(function(err){
if(err) {
res.send(500, {error: 'Database Error'});
}
res.redirect('/clubs/list');
});
},
};
MembersController.js
module.exports = {
list: function(req, res) {
Members.find({}).exec(function(err, member) {
if(err) {
res.send(500, {error: 'Database Error'});
}
res.view('pages/member-list', {members:member});
});
},
add: function(req, res) {
res.view('pages/member-add');
},
create: function(req, res) {
var memberName = req.body.memberName;
var clubId = req.body.clubId;
Members.create({memberName:memberName,
clubId:clubId}).exec(function(err){
if(err) {
res.send(500, {error: 'Database Error'});
}
res.redirect('/members/list');
});
},
};
routes.js
module.exports.routes = {
'/': {
view: 'pages/homepage',
},
'/clubs/list': {
view: 'pages/club-list',
controller: 'Clubs',
action: 'list'
},
'/clubs/add': {
view: 'pages/club-add',
controller: 'Clubs',
action: 'add'
},
'/clubs/create': {
controller: 'Clubs',
action: 'create',
},
'/members/list': {
view: 'pages/member-list',
controller: 'Members',
action: 'list'
},
'/members/add': {
view: 'pages/member-add',
controller: 'Members',
action: 'add'
},
'/members/create': {
controller: 'Members',
action: 'create',
},
};
I'm really new to Sails.js here and I find that it's quite difficult to get resources on this matter. I'm not sure if I put this in a way that you guys could understand. But do ask for more details if you guys need more understanding. Thank you in advance.
If I understand correctly, you're looking to create a one-to-many association between Clubs and Members. Here's how it should look in Clubs.js, your 'many':
attributes: {
...
members: {
collection: 'Members',
via: 'club'
}
}
Then in Members.js, your 'many':
attributes: {
...
club: {
model: 'Clubs'
}
}
When you do Club.find(), the members key will be an array of member ids. If you do Club.find().populate('member'), the members key will be an array of fully-populated member objects.
Here are the docs on associations.
This isn't directly related to your question, buy since you are new to Sails, I am including a comment that will give you some advice on how to best use the framework. I hope it goes well!
i am trying to make a game. I need tu create a Match. I think the problem on this Way. The User create a Match. In a third table I save playerId and gameId. When another user join the match, I save again, playerId and gameId. Then, I make a query with player with gameId in common, and start the game.
first, One User may have many Games. second, One Match may have many Games. this is the Match model:
module.exports = {
attributes: {
name: {
type: 'string'
},
description: {
type: 'string'
},
game: {
collection: 'game',
via: 'gameId',
}
}
};
This is the User model:
var bcrypt = require('bcrypt');
module.exports = {
attributes: {
name: {
type:'string'
},
email: {
type: 'email',
required: true,
unique: true
},
password: {
type: 'string',
},
passwordConfirmation: {
type: 'string'
},
passwordEncrypted: {
type: 'string'
},
creator: {
collection: 'game',
via: 'playerId'
},
toJSON: function(){
var obj = this.toObject();
delete obj.password;
delete obj.passwordConfirmation;
delete obj._csrf;
return obj;
}
}, beforeCreate: function(values, next){
console.log("Acabo de entrar a eforeCreate");
var password = values.password;
var passwordConfirmation = values.passwordConfirmation;
if(!password || !passwordConfirmation || password != values.passwordConfirmation) {
var passwordDoesNotMatchError = [{
name: 'passwordDoesNotMatchError',
message: 'Las contraseñas deben coincidir'
}]
return next({
err: passwordDoesNotMatchError
});
}
require('bcrypt').hash(values.password, 10, function passwordEncrypted(err, EncryptedPassword){
values.EncryptedPassword = EncryptedPassword;
next();
});
}
};
This is the Game model:
module.exports = {
attributes: {
gameId: {
model: 'match'
},
playerId: {
model: 'user'
}
}
};
finally, this is my controller:
module.exports = {
createMatch: function(req,res){
var matchObj = {
name: req.param('name'),
description: req.param('description'),
}
Match.create(matchObj, function(err, match){
if(err){
console.log("el error fue: " + err);
return res.send(err);
} console.log("Entro en create");
return res.json(match);
})
var gameObj = {
gameId: 'aclaration: I dont know how do I get the match.id',
playerId: req.session.me
}
Game.create(gameObj,function(err,game){
console.log("entro a GameCreate");
if(err){
return res.send(err);
} return res.json(game);
})
}
};
I can create the Match, but Game.create send this error:
_http_outgoing.js:344 throw new Error('Can\'t set headers after they are sent.'); ^
Error: Can't set headers after they are sent.
Somebody can help me? probably, I have many errors. Thanks.
Couple of things here:
Having an explicit Game model is not required in Sails. It can manage it implicitly, unless you want to store more information than just gameId and userId. So, you can just do away with Game model.
Please refer for async programming: How do I return the response from an asynchronous call?
Below code should work for you. Hope it helps.
module.exports = {
createMatch: function(req, res) {
var matchObj = {
name: req.param('name'),
description: req.param('description'),
};
Match.create(matchObj, function(err, match) {
if (err) {
console.log("el error fue: " + err);
return res.send(err);
}
console.log("Entro en create");
var gameObj = {
gameId: match.id,
playerId: req.session.me
};
Game.create(gameObj, function(err, game) {
console.log("entro a GameCreate");
if (err) {
return res.send(err);
}
return res.json(game);
// return res.json(match);
});
});
}
};
I'm evaluating OpenUI5 and I'm not clear about the binding concept.
In a XML login view, I have a Combobox that I want to populate after a successful login:
<ComboBox id="cboJoraniInstance" enabled="false" />
So, into my controller I've created an Ajax call with a parameter:
return Controller.extend("sap.ui.jorani.wt.controller.Login", {
onCheckEmail : function () {
var oDialog = this.getView().byId("BusyDialog");
oDialog.open();
var sMail = this.getView().byId("txtEmail").getValue();
var oListInst = this.getView().byId("cboJoraniInstance");
var aData = jQuery.ajax({
type : 'POST',
url : 'http://localhost/dummy/getJoraniInstances.php',
data: {
mail: sMail
},
async: false,
success : function(data,textStatus, jqXHR) {
//Link Combobox
var oModel = new sap.ui.model.json.JSONModel();
oModel.setData(data);
oListInst.setModel(oModel);
oListInst.bindElement("/Instances");
oListInst.bindProperty("value", "Url");
oListInst.bindProperty("name", "name");
oListInst.setEnabled();
},
error: function (jqXHR, textStatus, errorThrown){
MessageToast.show('An error occured');
}
});
oDialog.close();
},
});
The call to my web service is OK and returns:
{
"Instances": [{
"Name": "Local",
"IsDefault": true,
"Url": "http:\/\/localhost\/jorani\/"
}, {
"Name": "D\u00e9mo",
"IsDefault": false,
"Url": "https:\/\/demo.jorani.org\/"
}]
}
The code executes without error, but the control is not filled by my binding attempts.
I've checked the various SO questions on this topic and they all add a new ComboBox into the view dynamically, for example:
oListInst.placeAt("content");
But that is not what I want to achieve, I'd like to fill an existing object. Is it possible?
Concerning the view, if I fill the Combobox with the code below, it is working fine (but it doesn't use the binding feature):
$.each(data.Instances, function(i, obj) {
oListInst.addItem(new sap.ui.core.ListItem({key:obj.Url, text:obj.Name}));
});
In Article model, I want to save a list of categories:
var CategorySchema = new Schema({
name: String,
active: Boolean
});
var ArticleSchema = new Schema({
title: String,
description: String,
categories: [{ type : Schema.Types.ObjectId, ref: 'Category' }]
})
From the endpoint, I want to update article with categories. The update method looks like:
exports.update = function(req, res) {
if(req.body._id) { delete req.body._id; }
Article.findById(req.params.id, function (err, article) {
if (err) { return handleError(res, err); }
if(!article) { return res.send(404); }
var updated = _.merge(article, req.body);
updated.save(function (err, doc) {
console.log(doc);
if (err) { return handleError(res, err); }
return res.json(200, article);
});
});
};
Notice the console.log statement. In request.body, if I'm sending list of category ids, the console prints out an article with categories. However, when I look into the database, the category array is empty. Any pointer to how to solve this?