Adonis.js - Seeding Users and Profiles throwing DB error (Postgres) - adonis.js

I am trying to write a seed file for users and profiles with a one to one relationship and currently getting an "error: relation 'user_profiles' does not exist". From digging around, it seems like Adonis will assume this as a pivot table in the case of a many to many relationship. What I (think or intend to) have is a one to one relationship between users and profiles. Thanks in advance! Newbie to SQL and Adonis. As a side note, the user persists to the db, but there is no corresponding profile.
// My User Schema
class UserSchema extends Schema {
up () {
this.create('users', (table) => {
table.increments('id')
table.string('username', 80).notNullable().unique()
table.string('email', 254).notNullable().unique()
table.string('password', 60).notNullable()
// table.integer('profile_id').unsigned().references('id').inTable('userprofiles')
table.timestamps()
})
}
down () {
this.drop('users')
}
}
// My Profile Schema
class UserprofileSchema extends Schema {
up () {
this.create('userprofiles', (table) => {
table.increments()
table.string('first_name')
table.string('last_name')
// table.integer('user_id')
// .unsigned().references('id').inTable('users')
table.integer('user_id')
.unsigned()
.index('user_id')
table.foreign('user_id')
.references('users.id')
table.timestamps()
})
}
down () {
this.drop('userprofiles')
}
}
My User model includes the following relationship definition:
profile () {
return this.hasOne('App/Models/UserProfile')
}
// Seed script
class UserSeeder {
async run () {
try {
const user = await Factory.model('App/Models/User').create()
const userProfile = await Factory.model('App/Models/UserProfile').make()
userProfile.user_id = user.id
await user.profile().save(userProfile)
} catch (e) {
console.log('Error From Seeder: ', e);
}
}
}
Error code '42P01' and can post whole body if needed. Thanks!

On your Model userProfile, set table name as follows.
class User extends Model {
static get table () {
return 'userprofiles'
}
}

Related

Adonis migration to drop unique constraint

I am working on an Adonis JS project. I want to do the equivalent of ALTER TABLE products DROP CONSTRAINT unique_col_id where the unique_col_id is responsible for products.sku to be unique.
I tried this in AdonisJS database/migrations/filename.js:
'use strict'
/** #type {import('#adonisjs/lucid/src/Schema')} */
const Schema = use('Schema')
class ProductsAlterUniqueSkuSchema extends Schema {
up () {
this.alter('products', (table) => {
// alter table
table.integer('sku').unique(false);
})
}
down () {
this.table('products', (table) => {
// reverse alternations
})
}
}
module.exports = ProductsAlterUniqueSkuSchema
But I get the error Error: Duplicate column name 'sku'. How do I tell AdonisJS migration script to alter the table schema to drop the constraint?
You need to drop uniqueIndex. You can't alter this using .alter().
So for your solution, this will be the code:
'use strict'
/** #type {import('#adonisjs/lucid/src/Schema')} */
const Schema = use('Schema')
class ProductsAlterUniqueSkuSchema extends Schema {
up () {
this.alter('products', (table) => {
// alter table
table.dropUnique('sku')
})
}
down () {
this.table('products', (table) => {
// reverse alternations (check your first migration, and just repeat)
table.integer('sku').unique()
})
}
}
module.exports = ProductsAlterUniqueSkuSchema

How to redefine shape of query in Apollo GraphQl after a response

Working with apollo is great but how can you change the shape of the response from a query. I am using reactjs to display user details and their music information
Say I have a query
query {
userDetails {
id,
name,
music {
name,
type
}
}
is there a way to change the shape using apollo (not in reactjs) to something like
query {
userDetails {
id,
name,
musicName,
musicType
}
}
so that I get the second shape as the response rather than the first, then which I will have to change it using reactjs
You can create local-only fields that reads from the fetched fields by using the #client-directive and TypePolicies
Assuming the typename returned from the query is "User":
Query:
query {
userDetails {
id,
name,
music {
name,
type
}
musicName#client
musicType#client
}
Client setup:
const client = new ApolloClient({
cache: new InMemoryCache({
typePolicies: {
User: {
fields: {
musicName: {
read(_, { readField }) {
return readField('music').name;
}
},
musicType: {
read(_, { readField }) {
return readField('music').type;
}
},
}
}
}
}),
uri: "yourGraphqlServer.com"
});

Loopback get filtered result in the same order

I have two loopback model like
Model1
{
"id":"",
"name":"",
"model2Ids":[]
}
This model has an array of model 2 ids using the referencesMany relation.
I want to query Model from the remote method of model 1.
My remote method is as follows
Model1.customRemoteMethod = function(id, cb) {
var Model2 = Model1.app.models.model2;
Model1.findById(id, function(model1Error, model1Obj) {
if (model1Error) cb(model1Error);
if (model1Error.model2Ids) {
var model2Filter = {
'where': {
'id': {'inq': model1Obj.model2Ids}
}
};
Model1.find(model2Filter, function(model2Error, model2s) {
if (model2Error) cb(model2Error);
cb(null, Object.assign({}, JSON.parse(JSON.stringify((channelMapObj))), {
model2s: model2s
}));
});
}
})
})
I want the models that are returned(that is the filtered results) to be in the same array as that of my ids in Model1.Is there a way to do it.?
For example if I query using id 2,1,3.
Then the results should be the same order and not 1,2,3(as found in model 2).
The only solution that I have would be to loop over the id, and the use findById to get all results in same order.

RealmSwift update object in different threads(closures)

Kindly help with Real objects adding/updating
I'd like store and update User class.
User class consist of Client class,
Client class consist of Avatar property and Rooms List.
Issue is that I'm facing error "The Realm is already in a write transaction" because my Client class avatar property and rooms list are fetched and pushed to Realm in different closures at the same time.
func fetchRooms() {
roomsDelegate?.contactRooms(entityID: entityID,
success: {rooms in
self.addRooms(rooms: rooms)
},
fail: { error in
print (error)
})
}
func addRooms(rooms: [VMRoom]?) {
if let r = rooms {
do{
try realm?.write {
realm?.add(r, update: true)
self.rooms.append(objectsIn: r)
} }
catch let e {
print(e.localizedDescription)
}
}
}
func getAvatarURL() {
do{
try realm?.write {
avatarURL = avatarDelegate?.contactAvatarURL(eExtention: eExtention)
} }
catch let e {
print(e.localizedDescription)
}
}
Like Realm is saying, you've got an error in your app's logic if you're trying to open up two write transactions in one thread. I'd recommend you review your logic to see if you can make it more streamlined.
But in any case, to fix your current code, one way to mitigate this would be to check you're not already in a write transaction when you're setting the avatar URL.
func getAvatarURL() {
let inWriteTransaction = realm?.isInWriteTransaction
do {
if !inWriteTransaction {
realm?.beginWrite()
}
avatarURL = avatarDelegate?.contactAvatarURL(eExtention: eExtention)
if !inWriteTransaction {
try realm.commitWrite()
}
catch let e {
print(e.localizedDescription)
}
}

How to commit related models

I'm working with ember-pre4 and ember-data rev 11.
Models:
A = DS.Model.extend({
//some other fields
b: DS.hasMany('B')
})
B = DS.Model.extend({
//some other fields
a: DS.hasOne('A')
})
In my router I create an instance of model A and create an instance of model B and connect them. They both don't have server-side id. Something like this:
var a = A.createRecord();
b = B.createRecord();
b.set('a', a)
a.get('b').addObject(b)
When I want to save those models I make:
a.transaction.commit()
And I expected to see:
Save a with empty b // []
After saving a pass a's id into b and save b
After saving b refetch a
But unfortunately ember does 2 request in parallel and a's request data is:
"{//some fields, b: [/url_to_b//]}" // we dont have b's id
b's request data is:
"{//some fields } // we dont have a's id
What is the best way to solve this problem, does new ember have a default solution for my situation or I should do all stuff manually?
Solution:
I wrapped createRecord function in waitForParents function:
waitForParents:function (record, callback, context) {
var observers = new Em.Set();
record.eachRelationship(function (name, meta) {
var relationship = get(record, name);
if (meta.kind === 'belongsTo' && relationship && get(relationship, 'isNew')) {
var observer = function () {
relationship.removeObserver('id', context, observer);
observers.remove(name);
finish();
};
relationship.addObserver('id', context, observer);
observers.add(name);
}
});
finish();
function finish() {
if (observers.length === 0) {
callback.call(context);
}
}
},
createRecord:function (store, type, record) {
this.waitForParents(record, function () {
// createRecord code here
}
}