Can ORM sequelize have polymorphism? - orm

I have a model named User. Can I extend another model Admin/mod from User model? I have found the sequelize doc, but i didn't find out

Yes, check out the Associations documentation, or more fully in Scopes documentation.
From the docs:
this.Comment = this.sequelize.define('comment', {
title: Sequelize.STRING,
commentable: Sequelize.STRING,
commentable_id: Sequelize.INTEGER
});
this.Comment.prototype.getItem = function() {
return this['get' + this.get('commentable').substr(0, 1).toUpperCase() + this.get('commentable').substr(1)]();
};
this.Post.hasMany(this.Comment, {
foreignKey: 'commentable_id',
constraints: false,
scope: {
commentable: 'post'
}
});
this.Comment.belongsTo(this.Post, {
foreignKey: 'commentable_id',
constraints: false,
as: 'post'
});
this.Image.hasMany(this.Comment, {
foreignKey: 'commentable_id',
constraints: false,
scope: {
commentable: 'image'
}
});
this.Comment.belongsTo(this.Image, {
foreignKey: 'commentable_id',
constraints: false,
as: 'image'
});

Related

Relation doesn't exist, but it actually does

I set up the following tables and I use a many-to-many connection:
const Product = sequelize.define('Product',
{
name: DataTypes.STRING,
quantity: DataTypes.INTEGER
},
{ freezeTableName: true });
const Cart = sequelize.define('Cart',
{
customer_name: DataTypes.STRING,
total: DataTypes.FLOAT
});
const CartItem = sequelize.define('CartItem', {
selfGranted: DataTypes.BOOLEAN
},
{ timestamps: false });
Cart.belongsToMany(Product, { through: CartItem });
Product.belongsToMany(Cart, { through: CartItem });
And when I proceed to get the data, on the first request it sends me Relation doesn't exist error.
I forgot to remove the database re-sync.
db.sequelize.sync({ force: true }).then(() => {
console.log("Drop and re-sync db.");
});

SequelizeDatabaseError: SQLITE_ERROR: no such column: created_at

I'm trying to create a database with a foreign key but I kept getting the error of no such column: created_at, even tho I'm not using created_at somewhere in my code. I wonder why and how to patch this issue.
var User = sequelize.define('user', {
username: Sequelize.STRING,
myhash: Sequelize.TEXT,
mysalt: Sequelize.STRING,
keyword: Sequelize.STRING,
})
, Company = sequelize.define('company', {
keyword: Sequelize.STRING
});
User.belongsTo(Company);
var User = sequelize.define('user', {
username: Sequelize.STRING,
myhash: Sequelize.TEXT,
mysalt: Sequelize.STRING,
keyword: Sequelize.STRING,
}, {underscored: true})
, Company = sequelize.define('company', {
uuid: {
type: Sequelize.UUID,
primaryKey: true
}
});
User.belongsTo(Company);
created_at is automatically created for keeping the timestamp. You need to set the timestamp option to false like below to all your model definitions.
var User = sequelize.define('user', {
username: Sequelize.STRING,
myhash: Sequelize.TEXT,
mysalt: Sequelize.STRING,
keyword: Sequelize.STRING,
},{
timestamps: false
})

Relay mutation for React native returning 400 bad request?

I have been having SO much trouble trying to get a mutation to work.
Given this GraphQL Schema, can anyone PLEASE help me create a simple create User mutation? I don't understand what I am missing. I got it to a point where it throws a 400 error from the GraphQL server and it does not fire the resolve function.
var userType = new GraphQLObjectType({
name: 'User',
description: 'User creator',
fields: () => ({
id: {
type: new GraphQLNonNull(GraphQLString),
description: 'The id of the user.'
},
email: {
type: GraphQLString,
description: 'The email of the user.'
},
business: {
type: GraphQLString,
description:
'The name of the business of the user as the app refers to it.'
},
businessDisplayName: {
type: GraphQLString,
description: 'The name of the business of the user as they typed it in.'
},
trips: {
type: new GraphQLList(tripType),
description: 'The trips of the user, or an empty list if they have none.',
resolve: (user, params, source, fieldASTs) => {
var projections = infoToProjection(fieldASTs)
return Trip.find(
{
_id: {
// to make it easily testable
$in: user.trips.map(id => id.toString())
}
},
projections,
function(err, docs) {
return docs
}
)
}
}
})
})
var schema = new GraphQLSchema({
query: new GraphQLObjectType({
name: 'root',
fields: {
trips: {
type: new GraphQLList(tripType),
resolve: function() {
return Trip.find({})
}
},
users: {
type: new GraphQLList(userType),
resolve: function() {
return User.find({})
}
},
user: {
type: userType,
args: {
id: {
name: 'id',
type: new GraphQLNonNull(GraphQLString)
}
},
resolve: (root, { id }, source, fieldASTs) => {
return User.findOne(
{ _id: id },
infoToProjection(fieldASTs),
function(err, doc) {
return doc
}
)
}
},
trip: {
type: tripType,
args: {
id: {
name: 'id',
type: new GraphQLNonNull(GraphQLString)
}
},
resolve: (root, { id }, source, fieldASTs) => {
var projections = infoToProjection(fieldASTs)
return Trip.findOne({ _id: id }, projections, function(err, doc) {
return doc
})
}
}
}
}),
// mutation
mutation: new GraphQLObjectType({
name: 'Mutation',
fields: {
createUser: {
name: 'createUser',
type: userType,
args: {
input: { type: new GraphQLInputObjectType({
name: 'user',
fields: {
business: { type: GraphQLString },
email: { type: GraphQLString },
businessDisplayName: { type: GraphQLString }
}
})
}},
resolve: (parentValue, args) => {
let user = new User({ ...args.input })
user.save()
return user
}
}
})
})
export var getProjections = infoToProjection
export default schema
This works with GraphiQL using the following queries or mutations:
mutation {
createUser(input:{business:"business", email: "e#mai.l", businessDisplayName: "businessDN"}) {
id
email
business
businessDisplayName
}
}
fragment UserFragment on User {
id
business
businessDisplayName
trips{
title
}
}
{
hideya: user(id: "someid") {
...UserFragment
}
}
I finally fixed the problem. Tried to understand the source of the problem so I used a new NetworkLayer to enable appropriate logging and meaningful error messages. Then threw the an error when my mutation failed. The error message was : "Cannot query field clientMutationId". Looked that up and found that to be able to mutate objects you need to have that field on your GraphQL type. So I added it.
Lesson learned: I highly recommend using react-relay-network-layer.
More details:
Here is my code for it:
import {
RelayNetworkLayer,
urlMiddleware,
batchMiddleware,
} from 'react-relay-network-layer';
Relay.injectNetworkLayer(new RelayNetworkLayer([
batchMiddleware({
batchUrl: 'http://localhost:3000/graphql',
}),
urlMiddleware({
url: 'http://localhost:3000/graphql',
}),
]));
Note: This enables logging and by default it's a simple console.log.
Here is how I threw the error:
const params = {
email: email.toLowerCase(),
businessDisplayName: business,
business: business.toLowerCase()
}
var onSuccess = () => {
console.log('Mutation successful!')
}
var onFailure = transaction => {
var error = transaction.getError() || new Error('Mutation failed.')
console.error(error)
}
Relay.Store.commitUpdate(new FindOrCreateUser({ user: { ...params } }), { onFailure, onSuccess })
And of course you always need to clean your cache and restart your packager.

How can I override builtin login method in Loopback?

I've created a new User model, based on builtin one. I'm trying this:
module.exports = function(TiUser) {
TiUser.on('dataSourceAttached', function(obj) {
var login = TiUser.login;
TiUser.login = function(credentials, include, cb) {
var result = login.apply(this, credentials);
// Do my stuff
cb(null, my_data);
};
});
};
But I can't get it working... What is wrong? or how could this be done right?
Thanks
You may want to consider adding an afterRemote() hook to login(). Now you can achieve to add role( using Role model ) to user. For example:
TiUser.afterRemote('login', function(ctx, next) {
//add role to the user.
next();
});
At the end I've created a new method instead of overriding a current one:
module.exports = function(TiUser) {
TiUser.auth = function(credentials, include, fn) {
var self = this;
self.login(credentials, include, function(err, token) {
authInfo = {
token: token
};
fn(err, authInfo);
});
};
TiUser.remoteMethod(
'auth',
{
description: 'Login method with Role data information embedded in return',
accepts: [
{arg: 'credentials', type: 'object', required: true, http: {source: 'body'}},
{arg: 'include', type: ['string'], http: {source: 'query' },
description: 'Related objects to include in the response. ' +
'See the description of return value for more details.'}
],
returns: {
arg: 'accessToken', type: 'object', root: true,
description: 'User Model'
},
http: {verb: 'post'}
}
);
};

ExtJs:Initialize variable from Store

Hi i am using ExtHs 4.
I have a global variable which needs to be initialized from the store.
var cp=0;
Ext.onReady(function(){
Ext.define('Init', {
singleton: true,
cp: 0
});
Ext.define('loggedUserList', {
extend: 'Ext.data.Model',
fields: ['id','name']
});
loggedUser = Ext.create('Ext.data.Store', {
model: 'loggedUserList',
autoLoad: true,
proxy: {
type: 'ajax',
url : url+'/lochweb/loch/users/getLoggedUser',
reader: {
type: 'json',
root: 'provider'
}
},
listeners: {
load:function(loggedUser){
Init.cp = loggedUser.getAt(0).data.id;
}
}
});
});
i am using the value of cp in another url as follows,
Ext.define('vocbList', {
extend: 'Ext.data.Model',
fields: [
{ name: 'id', mapping: 'id' },
{ name: 'code', mapping: 'code' },
{ name: 'loinc', mapping: 'loinc.loincNumber' }
]
});
var vocabulary = Ext.create('Ext.data.Store', {
model: 'vocbList',
autoLoad: true,
proxy: {
type: 'ajax',
url : url+'/lochweb/loch/vocabulary/getVocabularyByProvider?providerId='+Init.cp,
reader: {
type: 'json',
root: 'Vocabulary'
}
}
});
but its value is still 0.How to assign its value form store so that it can be reused for other purpose.
Thanks
What you need is a callback.
Store call is being done asynchronously so that the browser will not freeze while the store get the data from the database.
me.vocabulary.load({
scope: this,
callback: function (records, operation, success) {
//here the store has been loaded so records are not empty
}
});
In your Ext.onReady, define a global class like this:
Ext.define('Init', {
singleton: true,
cp: 0
});
Then you can get or set cp anywhere you want:
Init.cp = 'some';
var myCp = Init.cp;