I wrote a custom data type by extending Abstract, like in the example listed for the following link: https://sequelize.org/v5/manual/data-types.html. Everything appears to work until I try to save foreign keys, in this case it continues to generate a new UUID instead of getting the foreign key passed in the object to the create method.
How should I accommodate foreign keys in this case? Which method call should I overload to handle a getter situation where I need to pass in values?
The code below outlines the extended class I am using
class BinToUUID extends ABSTRACT {
toString(options) {
return this.toSql(options);
}
toSql() {
return 'BINARY(16)';
}
validate(value) {
console.log(value);
}
_stringify(value, options) {
return `UUID_TO_BIN(${options.escape(value)})`;
}
_bindParam(value, options) {
return `UUID_TO_BIN('${options.escape(value)}')`;
}
parse(value) {
return uuidv1.parse(value);
}
_sanitize(value) {
if (value instanceof Buffer) {
const str = value.toString('hex');
return [
str.slice(0, 8),
str.slice(8, 12),
str.slice(12, 16),
str.slice(16, 20),
str.slice(20, 32),
].join('-');
} else {
const uuid = uuidv1();
return uuid;
}
return value;
}
}
Here is a sample of the model I am using it in:
sequelize.define("room", {
roomId: {
primaryKey: true,
allowNull: false,
type: Sequelize.BinToUUID,
defaultValue: Sequelize.BinToUUID,
validate: {
notNull: true
}
},
name: {
type: DataTypes.STRING(10)
},
userId: {
type: Sequelize.BinToUUID,
references: {
model: 'user',
key: 'userId',
}
},
groupId: {
type: Sequelize.BinToUUID,
references: {
model: 'group',
key: 'groupId',
}
},
createdAt: {
type: DataTypes.DATE
},
updatedAt: {
type: DataTypes.DATE
}
}, {
freezeTableName: true
});
Here are the associations for the tables:
db.Room.User = db.Room.hasOne(db.User, {
foreignKey: ‘roomId'
});
db.Room.Group = db.Room.hasOne(db.Group, {
foreignKey: ‘groupId'
});
This is the create method begin called to save the room:
Room.create(room, {
include: [{
association: Room.User
}, {
association: Room.Group
}]
});
I am just trying to save the foreign keys to this table. When I look into the database tables for User and Group, the values do not match the uuid primary key values. It seems like the BinToUUID datatype is overwriting the UUID that is getting passed to create method.
For one-to-one (primary/foreign key relationship), check out belongsTo / HasOne associations
belongsTo
https://sequelize.org/v5/class/lib/model.js~Model.html#static-method-belongsTo
which has the following example:
Profile.belongsTo(User) // This will add userId to the profile table
HasOne
https://sequelize.org/v5/class/lib/associations/has-one.js~HasOne.html:
This is almost the same as belongsTo with one exception - The foreign key will be defined on the target model.
See this tutorial for examples: https://sequelize.org/v4/manual/tutorial/associations.html
This (unofficial?) article shows how foreign key is being handled: https://medium.com/#edtimmer/sequelize-associations-basics-bde90c0deeaa
I'm trying to use normalizer to normalize some JSON. My JSON looks like
total: 8029,
items: [
{
id: 1,
name: 'Jacket1',
sku: '123',
upc: '1',
price: '99.99',
images: ['url1', 'url2'],
category: 'clothing',
thumbnail:
'https://cdn.zeplin.io/5969021e44c5978909d5278b/assets/1CE5FF07-E70F-4413-85BF-49C08AA559DE.png',
}, ...
and from the examples, I thought this might work
const itemSchema = new schema.Entity('items')
const itemsSchema = new schema.Entity('result', {
items: [itemSchema],
})
const foo = normalize(fakeDatabase, itemsSchema)
But I end up with one result that is undefined, and that undefined value has some funky stuff in it.
What am I doing wrong?
I don't believe itemsSchema is necessary. Try either:
normalize(fakeDatabase, { items: new schema.Array(itemSchema) })
or
normalize(fakeDatabase, { items: [itemSchema] })
I'm looking for a performant way to update selected records in a collection based on the presence of the record's ID in a reference array. For example, given a reference array of [1,2,5] I want each record in the collection with those IDs to be given an attribute of $selected: true. Each record in the collection will be associated with a checkbox in the view and $selected items will be checked (fiddle)
I've started with the approach below (coffeescript) but I'm new to Lodash so I thought I'd ask for some feedback. Also, I'm not sure what the cleanest way is to set $selected: false to the alternate records?
# Whole Collection
collection = [
{id:1, name: "one"},
{id:2, name: "two"},
{id:3, name: "three"},
{id:4, name: "four"},
{id:5, name: "five"}
]
# Mark subset as selected
for id in [1,2,5]
_.where( collection, 'id':id ).forEach( (record) ->
record.$selected = true
)
Here's a fiddle...
http://jsfiddle.net/zd78e4bj/
EDIT
Added reference to two-way binding $selected elements to checkboxes in the view
I would do something like this (sorry it's not CoffeScript, but you get the idea):
var collection = [
{ id:1, name: 'one' },
{ id:2, name: 'two' },
{ id:3, name: 'three' },
{ id:4, name: 'four' },
{ id:5, name: 'five'}
];
var ids = [ 1, 2, 5 ];
_(collection)
.indexBy('id')
.at(ids)
.each(_.ary(_.partialRight(_.assign, { $selected: true }), 1))
.value();
console.log(collection);
// →
// [
// { id: 1, name: 'one', $selected: true },
// { id: 2, name: 'two', $selected: true },
// { id: 3, name: 'three' },
// { id: 4, name: 'four' },
// { id: 5, name: 'five', $selected: true }
// ]
First, we create an intermediary object using indexBy(). The keys are the id values in collection. Next, we pass at() the ids we're interested in. This builds a new collection containing only the ids we're after.
The last step is to use each() to add the $selected property. This is done by combining partialRight(), assign(), and ary(). The partially-applied argument is the new $selected property. We use ary() to make sure the callback passed to each() only has one argument.
You can use the map or forEach function to do all of this either in Lodash or native JavaScript. Map creates a new list and forEach will mutate the existing list.
The key to these is the transformation function. This function will set the $selected to true or false if it exists or not in the ids collection.
function mark(item) {
item['$selected'] = (ids.indexOf(item.id) > -1);
return item;
}
You could build a more generic transformer using:
function markItemByList(list, property, searchField) {
return function(item) {
item[property] = (list.indexOf(item[searchField]) > -1);
return item;
}
}
Coffeescript would be:
markItemByList = (list, property, searchField) ->
(item) ->
item[property] = (list.indexOf(item[searchField])) > -1)
item
If you want a mutable implementation:
function select(ids, collection) {
collection.forEach(markItemByList(ids, '$selected', 'id'));
}
Here's a lodash immutable implementation:
function select(ids, collection) {
return _.map(collection, markItemByList(ids, '$selected', 'id'));
}
Here's a pure JavaScript immutable implementation:
function select(ids, collection) {
return collection.map(markItemByList(ids, '$selected', 'id'));
}
Here's an angular implementation:
angular.forEach(collection, markItemsByList(ids, '$selected', 'id'));
I have defined my model with this field
base: {
type: 'string',
in: ['A', 'B', 'C']
}
I was wondering if there is a way I could get the possible enum values to use in the view for a dropdown or if I need to have the it hardcoded somewhere?
You can always retrieve the attributes of a model with <model>.attributes. For example, given:
// api/models/Foo.js
module.exports = {
attributes: {
base: {
type: 'string',
in: ['A', 'B', 'C']
}
}
};
You can access Foo.attributes.base.in or sails.models.foo.base.in later to retrieve the in values.
i'm having trouble trying to figure out how this is happening. i'm using Extjs and AJAX with JsonStore from my callback my page in ASP call the database and return some fields in this fields there is a Date and this date return the proper date ex.: "date_creat_post": "29\u002F04\u002F2011"...
Now once i look at my output from this in my page in a datagrid i'm getting the following:
04/05/2013 <----> the date it return in the callback is 04/05/2011
06/05/2012 <----> the date it return in the callback is 06/05/2010
07/04/2012 <----> the date it return in the callback is 07/04/2010
I looked all threw my code to see if they're is a place where i am adding 1 year to the date.
but can't find it. i have been trying now for at least 2 days to figure this out.
Here's my code:
Ext.onReady(function(){
Ext.QuickTips.init();
// for this demo configure local and remote urls for demo purposes
var url = {
local: '', // static data file
remote: '../myurl.asp'
};
// configure whether filter query is encoded or not (initially)
var encode = true;
// configure whether filtering is performed locally or remotely (initially)
var local = false;
var PostStore = new Ext.data.JsonStore({
// store configs
autoDestroy: true,
baseParams : {filter : '[{"type":"boolean","value":false,"field":"is_sent_post"}]'},// we start only with is_sent == false
url: url.remote,
remoteSort: false,
sortInfo: {
field: 'date_creat_post',
direction: 'DESC'
},
storeId: 'Post_Store',
// reader configs
idProperty: 'id_post',
root: 'Post',
totalProperty: 'totalcount',
fields: [{
name: 'id_post',
type: 'number'
}, {
name: 'name_post',
type: 'string'
}, {
name: 'date_creat_post',
type: 'date'//,
//dateFormat: 'Y-m-d H:i:s'
}, {
name: 'from_addr_post',
type: 'string'
}, {
name: 'sender_name_post',
type: 'string'
}, {
name: 'is_sent_post',
type: 'boolean'
}, {
name: 'date_sending_post',
type: 'date'//,
//dateFormat: 'Y-m-d H:i:s'
}, {
name: 'html_post',
type: 'string'
}, {
name: 'list_send_post',
type: 'number'
}],
writer: new Ext.data.JsonWriter({
writeAllFields: true
}),
autoSave: false,
batch: true
});
var filters = new Ext.ux.grid.GridFilters({
// encode and local configuration options defined previously for easier reuse
encode: encode, // json encode the filter query
local: local, // defaults to false (remote filtering)
filters: [{
type: 'numeric',
dataIndex: 'id_post'
}, {
type: 'string',
dataIndex: 'name_post'
}, {
type: 'date',
dataIndex: 'date_creat_post'
}, {
type: 'string',
dataIndex: 'from_addr_post'
}, {
type: 'string',
dataIndex: 'sender_name_post'
}, {
type: 'boolean',
dataIndex: 'is_sent_post'
}, {
type: 'date',
dataIndex: 'date_sending_post'
}, {
type: 'string',
dataIndex: 'html_post'
}, {
type: 'numeric',
dataIndex: 'list_send_post'
}]
});
// use a factory method to reduce code while demonstrating
// that the GridFilter plugin may be configured with or without
// the filter types (the filters may be specified on the column model
var createColModel = function (finish, start) {
var columns = [{
dataIndex: 'id_post',
hidden:true,
header: 'Id',
// instead of specifying filter config just specify filterable=true
// to use store's field's type property (if type property not
// explicitly specified in store config it will be 'auto' which
// GridFilters will assume to be 'StringFilter'
filterable: true
//,filter: {type: 'numeric'}
}, {
dataIndex: 'name_post',
header: 'Subject',
width: 150,
id: 'postname',
filter: {
type: 'string'
// specify disabled to disable the filter menu
//, disabled: true
}
}, {
dataIndex: 'date_creat_post',
header: 'Date Created',
renderer: Ext.util.Format.dateRenderer('d/m/Y'),
filter: {
type: 'date' // specify type here or in store fields config
}
}, {
dataIndex: 'from_addr_post',
header: 'From Address',
hidden:true,
id: 'fromaddress',
filter: {
type: 'string'
// specify disabled to disable the filter menu
//, disabled: true
}
}, {
dataIndex: 'sender_name_post',
header: 'Sender Name',
id: 'sendername',
filter: {
type: 'string'
// specify disabled to disable the filter menu
//, disabled: true
}
}, {
dataIndex: 'is_sent_post',
header: 'Status',
filter: {
type: 'boolean' // specify type here or in store fields config
},
renderer: function(value) {
var rtn = (value == 1) ? 'sent' : 'stand-by';
return rtn
}
}, {
dataIndex: 'date_sending_post',
header: 'Sending Date',
hidden:true,
//renderer: Ext.util.Format.dateRenderer('d/m/Y'),
filter: {
type: 'date' // specify type here or in store fields config
}
}, {
dataIndex: 'list_send_post',
header: 'Opticians list',
hidden:true,
id: 'optlist',
filter: {
type: 'number'
// specify disabled to disable the filter menu
//, disabled: true
}
}];
return new Ext.grid.ColumnModel({
columns: columns.slice(start || 0, finish),
defaults: {
sortable: true
}
});
};
/*
//======================contextMenu triggered by right click========================================
*/
var doRowCtxMenu = function ( thisGrid, rowIndex,cellIndex, evtObj )
{
//Ext.popup.msg('Done !', 'Right clicked !');
evtObj.stopEvent();
var sm = thisGrid.getSelectionModel();
var records = sm.getSelections(); // returns an array of Ext.data.Records
try
{
//var r = records[0]; // get the 1st Ext.data.Record of the list
thisGrid.rowCtxMenu = new Ext.menu.Menu({
items: [{
text : '<span style="color:red;">Delete Selected Email ?</span>',
handler : function () {
deletePost(records,thisGrid);
}
}]
});
thisGrid.rowCtxMenu.showAt(evtObj.getXY());
}
catch(err)
{
Ext.popup.msg('Warning !', 'You need to select a row first !');
}
};
/*
//======================END contextMenu triggered by right click========================================
//======================Delete Post Fonction =================================================
*/
function deletePost(records,thisGrid)
{
Ext.Msg.show({
title :'Warning !',
msg : 'You are about to delete 1 email !',
buttons : Ext.Msg.YESNOCANCEL,
fn : function(btn){
if (btn=='yes')
{
var store = thisGrid.getStore();
var s = thisGrid.getSelectionModel().getSelections();
for(var i = 0, r; r = s[i]; i++){
store.remove(r);
}
store.proxy.conn.url = '../myurl.asp';
store.save();
lastOptions = store.lastOptions;
/*Ext.apply(lastOptions.params, {
//myNewParam: true
});*/
store.load(lastOptions);
}
},
animEl : 'elId'
});
}
/*
//======================End delete Function========================================
*/
var Postgrid = new Ext.grid.GridPanel({
id:'post_grid',
border: false,
width: 462,
height:250,
store: PostStore,
colModel: createColModel(8),
loadMask: true,
viewConfig:{
emptyText:'No Post to display, change/clear your filters, refresh the grid or add a new Email!'
},
plugins: [filters],
sm: new Ext.grid.RowSelectionModel({
singleSelect: true,
listeners: {
rowselect: function(sm, row, rec) {
Ext.getCmp("post_form").getForm().loadRecord(rec);
//Ext.getCmp("htmlEdit").setValue("sdcdsdcdscsdc");
}
}
}),
//autoExpandColumn: 'company',
listeners: {
cellcontextmenu : doRowCtxMenu,
render: {
fn: function(){
PostStore.load({
params: {
start: 0,
limit: 50
}
});
}
}
},
bbar: new Ext.PagingToolbar({
store: PostStore,
pageSize: 50,
plugins: [filters]
})
});
// add some buttons to bottom toolbar just for demonstration purposes
Postgrid.getBottomToolbar().add([
'->',
{
text: 'Clear Filter Data',
handler: function () {
Postgrid.filters.clearFilters();
}
}
]);
var panelGrid = new Ext.Panel({
width : 462,
height : 250,
layout : 'fit',
renderTo: 'post-grid',
items: Postgrid
});
});
i will give my callback in firebug json:
{"totalcount":3, "Post": [{"id_post": 83,"name_post": "ghfgh","date_creat_post": "29\u002F04\u002F2011","from_addr_post": "fgh#sdf.com","sender_name_post": "gfh","is_sent_post": false,"date_sending_post": "29\u002F04\u002F2011","html_post": "<p>dfgdgdgd<\u002Fp>","list_send_post": null},{"id_post": 61,"name_post": "thomas test","date_creat_post": "28\u002F07\u002F2010","from_addr_post": "","sender_name_post": "","is_sent_post": false,"date_sending_post": "28\u002F07\u002F2010","html_post": "<p>test test test ets<\u002Fp>","list_send_post": null},{"id_post": 59,"name_post": "kevin test","date_creat_post": "29\u002F06\u002F2010","from_addr_post": "kevin#art-systems.net","sender_name_post": "kevin#art-systems.net","is_sent_post": false,"date_sending_post": "29\u002F06\u002F2010","html_post": "<p>jkljljoi ioijiio ijiojio oijio joijoi<\u002Fp>\u000A<p> <\u002Fp>\u000A<p><span style=\u0022background-color: #ffffff;\u0022>igiuihhuhi<\u002Fspan><\u002Fp>","list_send_post": null}]}
Thanks in advance i hope some on on the wicked web can help me....
cheers.
so after trying many solution giving to be i came to this has problem
finally the the date example after many attemps to format and inserting in my msSQL database
this problem is the problem : 13\09\2011 (d/m/Y) becomes this 09/01/2012 (d/m/Y) so for some reason the month 13 is being added to the month so say the 13 month doesn't exist so the date will go to 09/01/2012....
after looking again it's the format that doesn't seem ok so i changed it de (m/d/Y) and now im getting a sql error when i hit 13 day on my datefield in (extjs).
"The conversion of a varchar data type to a datetime data type resulted in an out-of-range value."
and on and on does anyone have any ideas now ????
Instead of using the built in Ext.util.Format.dateRenderer, you could try creating one of your own that parses the Date as desired.
ataIndex: 'date_creat_post',
header: 'Date Created',
renderer: daterenderer
And then a function for your daterenderer:
function dateRenderer(value, id, r) {
var myDate = r.data['date_creat_post'];
// do some things here to strip out the date and make it into a happy format
var d = new Date(myDate);
return d.format('d/m/Y');
}