Retrieving Parents and Children - Self Referencing Entity gorm - parent

I have a table that have a hierarchy structure with a parent having many children and a children having many parents.
As an example the following struct:
type User struct {
gorm.Model
Name string
SubUsers []*User `gorm:"many2many:user_sub_users;constraint:OnDelete:CASCADE"`
SuperUsers []*User `gorm:"many2many:user_sub_users.......` // no idea what to fill here
}
What's the gorm configuration I need to add to being able to retrieve the super users (parents) for one entity?
So, as an example, imagine that I have the following
Table users
| ID | name |
--------------=
| 1 | Alice |
| 2 | Bob |
| 3 | Joe |
| 4 | Manuel |
---------------
Table users_sub_users
| ID | user_id | sub_user_id |
-------------------------------
| 1 | 1 | 2 |
| 2 | 1 | 3 |
| 3 | 4 | 1 |
-------------------------------
So if I retrieve the user Alice, I want to get the following:
Alice ->
SubUsers: [Bob, Joe]
SuperUsers: [Manuel]

You can specify the fields in the table user_sub_users with joinForeignKey and joinReferences.
Instead of:
SubUsers []*User `gorm:"many2many:user_sub_users"`
it would be more explicit:
SubUsers []*User `gorm:"many2many:user_sub_users;joinForeignKey:sub_user_id;joinReferences:user_id;"`
For the SuperUsers just swap the fields:
SuperUsers []*User `gorm:"many2many:user_sub_users;joinForeignKey:user_id;joinReferences:sub_user_id;"`
Minimal example:
package main
import (
"fmt"
"github.com/glebarez/sqlite"
"gorm.io/gorm"
)
type User struct {
gorm.Model
Name string
SubUsers []*User `gorm:"many2many:user_sub_users;joinForeignKey:sub_user_id;joinReferences:user_id;"`
SuperUsers []*User `gorm:"many2many:user_sub_users;joinForeignKey:user_id;joinReferences:sub_user_id;"`
}
func main() {
db, err := gorm.Open(sqlite.Open("test.db"), &gorm.Config{})
if err != nil {
panic(err)
}
db.AutoMigrate(&User{})
alice := &User{Name: "Alice"}
db.Create(alice)
bob := &User{Name: "Bob"}
db.Create(bob)
joe := &User{Name: "Joe"}
db.Create(joe)
manuel := &User{Name: "Manuel"}
db.Create(manuel)
err = db.Model(alice).Association("SubUsers").Append(bob, joe)
if err != nil {
panic(err)
}
err = db.Model(manuel).Association("SubUsers").Append(alice)
if err != nil {
panic(err)
}
var user User
err = db.Preload("SubUsers").Preload("SuperUsers").First(&user, alice.ID).Error
if err != nil {
panic(err)
}
for _, u := range user.SubUsers {
fmt.Println("Subuser", u.Name)
}
for _, u := range user.SuperUsers {
fmt.Println("Superuser", u.Name)
}
}

Related

How to match keywords with pest?

I'm trying to parse a line like this
MyTupleComponent str, str
with grammar
cname = _{ (ASCII_ALPHANUMERIC | "_")+ }
ints = { "i8" | "i16" | "i32" | "i64" | "i128" | "isize" }
uints = { "u8" | "u16" | "u32" | "u64" | "u128" | "usize" }
strings = { "str" | "String" }
types = { strings | ints | uints }
tuple_component = { cname ~ (types ~ ("," ~ types)?)+ }
But end up with
Err(Error { variant: ParsingError { positives: [types], negatives: [] }, location: Pos(20), line_col: Pos((1, 21)), path: None, line: "MyTupleComponent str, str", continued_line: None })
Anyone know why the rule don't matches correctly?
You can take two roads:
As #ZachThompson pointed out, define WHITESPACE. If you do, make cname atomic, to prevent it from capturing alphanumerics AND spaces.
This test grammar seems fine:
WHITESPACE = _{ " " }
cname = #{ (ASCII_ALPHANUMERIC | "_")+ }
ints = { "i8" | "i16" | "i32" | "i64" | "i128" | "isize" }
uints = { "u8" | "u16" | "u32" | "u64" | "u128" | "usize" }
strings = { "str" | "String" }
types = { strings | ints | uints }
tuple_component = { cname ~ (types ~ ("," ~ types)?)+ }
file = { tuple_component ~ EOI }
Otherwise, you can account for spaces manually. This approach would work too, but it's not scalable with a growth of a grammar.
P.S. Is your intention to parse expressions like MyTupleComponent str, str str, str, without the comma to separate a second tuple from the first? It currently parses fine. You may want to simplify the rule to
tuple_component = { cname ~ types ~ ("," ~ types)* }

How to count number of times the primary key of a row is referenced in a specific table with Objection.js

(Using PostgreSQL)
So, I have these (User and Vote) Objection.js models:
const { Model } = require('objection');
class User extends Model {
static get tableName() {
return 'users';
}
static get relationMappings() {
return {
posts: {
relation: Model.HasManyRelation,
modelClass: require('./Post'),
join: {
from: 'users.id',
to: 'posts.userId',
},
},
comments: {
relation: Model.HasManyRelation,
modelClass: require('./Comment'),
join: {
from: 'users.id',
to: 'comments.userId'
}
},
votes: {
relation: Model.HasManyRelation,
modelClass: require('./Vote'),
join: {
from: 'users.id',
to: 'votes.userId'
}
}
};
}
}
module.exports = User;
const { Model } = require('objection');
class Vote extends Model {
static get tableName () { return 'votes' }
static get relationalMappings () {
return {
user: {
relation: Model.BelongsToOneRelation,
modelClass: require('./User'),
join: {
from: 'votes.userId',
to: 'users.id'
}
},
post: {
relation: Model.BelongsToOneRelation,
modelClass: require('./Post'),
join: {
from: 'votes.postId',
to: 'posts.id'
}
}
}
}
}
module.exports = Vote;
The psql command \d users returns:
Table "public.users"
Column | Type | Collation | Nullable | Default
-------------+------------------------+-----------+----------+-------------------
id | uuid | | not null | gen_random_uuid()
username | character varying(128) | | not null |
displayname | character varying(128) | | not null |
email | character varying(256) | | not null |
description | character varying(256) | | |
password | character varying(512) | | not null |
Indexes:
"users_pkey" PRIMARY KEY, btree (id)
"users_id_index" btree (id)
Referenced by:
TABLE "comments" CONSTRAINT "comments_userid_foreign" FOREIGN KEY ("userId") REFERENCES users(id)
TABLE "posts" CONSTRAINT "posts_userid_foreign" FOREIGN KEY ("userId") REFERENCES users(id)
TABLE "votes" CONSTRAINT "votes_userid_foreign" FOREIGN KEY ("userId") REFERENCES users(id)
And the psql command \d votes returns:
Table "public.votes"
Column | Type | Collation | Nullable | Default
--------+---------+-----------+----------+-------------------
id | uuid | | not null | gen_random_uuid()
userId | uuid | | not null |
postId | uuid | | not null |
up | boolean | | not null |
down | boolean | | not null |
Indexes:
"votes_pkey" PRIMARY KEY, btree (id)
"votes_id_index" btree (id)
Foreign-key constraints:
"votes_postid_foreign" FOREIGN KEY ("postId") REFERENCES posts(id)
"votes_userid_foreign" FOREIGN KEY ("userId") REFERENCES users(id)
What i would like to do is use some sort of Model class method (on the class User) to set the properties upvotes (number of Votes with up set to true), downvotes (number of Votes with down set to true) and balance (upvotes - downvotes).

Jest mocking multiple files and static methods

I am trying to write a test case using Jest. How can I write the test case for below snippets? A is a separate file and Three is a different file. I need to write the test cases as separate files as like unit test cases.
I am stuck in writing the static methods calling and mocking the multiple inputs. See below what I have tried also.
const one = require('../one');
const two = require('../two');
const three = require('../three');
class A {
public static checkTesting(param) {
switch (param) {
case 'one':
return one;
case 'two':
return two;
default:
return three;
}
}
constructor(param) {
this.testing = A.checkTesting(param);
}
}
module.exports = A;
const multiple = require('../multiple')(module);
const config = require('../config');
class Three {
public static sampleTestingWrite() {
return {
b: param => multiple[config.access](param)
};
}
constructor() {
this.sampleTesting = Three.sampleTestingWrite();
}
}
module.exports = Three;
A.test.js:
const One = require('../one');
const Two = require('../two');
const Three = require('../three');
const A = require('..');
jest.mock('../one');
jest.mock('../two');
jest.mock('../three');
describe('A test cases', () => {
test('should initiate the constructor', () => {
const mockStaticFunction = jest.fn();
mockStaticFunction.mockReturnValue('returns an object which does something on Multiple');
const MockA = new A('one');
console.log(MockA);
Console.mockImplementation(() => ({}));
console.log(logMedium);
expect(Console).toHaveBeenCalledTimes(1);
});
});
If you want to test if the constructor of A is called correctly. There is no need to mock one, two, three modules. Only you need to mock/spyOn is
checkTesting static method of A.
Here is the solution, I use typescript
import one from './one';
import two from './two';
import three from './three';
class A {
public static checkTesting(param) {
switch (param) {
case 'one':
return one;
case 'two':
return two;
default:
return three;
}
}
private testing;
constructor(param) {
this.testing = A.checkTesting(param);
}
}
export { A };
Unit test:
import { A } from './a';
describe('A', () => {
describe('checkTesting', () => {
it('should initiate the constructor', () => {
jest.spyOn(A, 'checkTesting').mockReturnValue({ name: 'never mind' });
const param = 'one';
const a = new A(param);
expect(a).toBeInstanceOf(A);
expect(A.checkTesting).toBeCalledWith(param);
});
});
});
Unit test result with coverage:
PASS src/mock-function/57624975/a.spec.ts
A
checkTesting
✓ t1 (8ms)
----------|----------|----------|----------|----------|-------------------|
File | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s |
----------|----------|----------|----------|----------|-------------------|
All files | 73.33 | 0 | 66.67 | 73.33 | |
a.ts | 66.67 | 0 | 66.67 | 66.67 | 7,9,11,13 |
one.ts | 100 | 100 | 100 | 100 | |
three.ts | 100 | 100 | 100 | 100 | |
two.ts | 100 | 100 | 100 | 100 | |
----------|----------|----------|----------|----------|-------------------|
Test Suites: 1 passed, 1 total
Tests: 1 passed, 1 total
Snapshots: 0 total
Time: 1.649s, estimated 3s

Can I replace values in a table with SpecFlow.Assist?

I currently have a step to verify a payment
Then I have these payments:
| Payment Type | Amount |
| Cash | 1.20 |
I would like to replace the 'Amount' with a variable, such as bill total which would be in the TestContext.
Then I have these payments:
| Payment Type | Amount |
| Cash | <billTotal> |
I've attempted to pre-process the table before creating my set, but I cannot assign to the TableRow value. Is there a standard way to achieve this? Is there a different approach I should be taking?
I ended up using something like this before creating my set:
public void AdjustTable(Table table)
{
foreach (var row in table.Rows)
{
foreach (var key in row.Keys)
{
if (row[key] == "<userFirstName>")
{
row[key] = this.testContext.CustomerProfile.Customer.Name.First;
}
else if (row[key] == "<userLastName>")
{
row[key] = this.testContext.CustomerProfile.Customer.Name.Last;
}
}
}
}
Still open to suggestions!!

Multitouch Piano Dialog Based application

I have made a dialog based Piano application in which i am handling Multitouch messages . I have two classes One is CMIDIKeyboard in which i am handling touch down messages as follows
LRESULT CMIDIKeyboard::OnTouchMessage( WPARAM wParam, LPARAM lParam ){
//Insert handler code here to do something with the message or uncomment the following line to test
//-------------------saurabh code------------------------------------------------------------------
UINT cInputs = (int) wParam; // Number of actual per-contact messages
TOUCHINPUT* pInputs = new TOUCHINPUT[cInputs]; // Allocate the storage for the parameters of the per-contact messages
if (pInputs == NULL)
{
return 0;
}
// Unpack message parameters into the array of TOUCHINPUT structures, each
// representing a message for one single contact.
if (GetTouchInputInfo((HTOUCHINPUT)lParam, cInputs, pInputs, sizeof(TOUCHINPUT)))
{
// For each contact, dispatch the message to the appropriate message
// handler.
for (unsigned int i = 0; i < cInputs; i++)
{
if (pInputs[i].dwFlags & TOUCHEVENTF_DOWN)
{
CPoint point;
CRect rect;
GetClientRect(&rect);
point=CPoint(pInputs[i].x-rect.left,pInputs[i].y-rect.top);
m_CurrKey= CPianoCtrl::FindKey(point);
m_Keys[m_CurrKey]->NoteOn(m_NoteOnColor,rect);
NotifyNoteOn(m_LowNote+m_CurrKey);
findchords(m_LowNote+m_CurrKey);
InvalidateRect(&rect);
CWnd::OnTouchMessage(wParam,lParam);
}
else if (pInputs[i].dwFlags & TOUCHEVENTF_UP)
{
//MessageBox("touchup!", "touchup!", MB_OK);
// g_pIManipProc->ProcessUp(pInputs[i].dwID, (FLOAT)pInputs[i].x, (FLOAT)pInputs[i].y);
}
else if (pInputs[i].dwFlags & TOUCHEVENTF_MOVE)
{
//MessageBox("touchmove!", "touchmove!", MB_OK);
//g_pIManipProc->ProcessMove(pInputs[i].dwID, (FLOAT)pInputs[i].x, (FLOAT)pInputs[i].y);
}
}
}
else
{
// error handling, presumably out of memory
ASSERT(FALSE && L"Error: failed to execute GetTouchInputInfo");
delete [] pInputs;
return 0;
//break;
}
if (!CloseTouchInputHandle((HTOUCHINPUT)lParam))
{
// error handling, presumably out of memory
ASSERT(FALSE && L"Error: failed to execute CloseTouchInputHandle");
delete [] pInputs;
return 0;
//break;
}
delete [] pInputs;
//--------------------------------------------------------saurabh code ends-----------------
//MessageBox("touch!", "touch!", MB_OK);
return 0;}
But on playing the piano keys first touch is playing proper ,but more than 1 touch is playing on piano keys enabling the last key on the right side irrespective of the touch position.
// ----------------------
// | | || | | | || || | |
// | |_||_| | |_||_||_| |
// | | | | | | | |
// ----------------------
// ^ ^
| |
one point More than
touch one touch
Can anybody please guide me or correct me please.
The TOUCHINFO documentation says:
x    The x-coordinate (horizontal point) of the touch input. This member is indicated in hundredths of a pixel of physical screen coordinates.
You cannot subtract a value measured in whole pixels (rect.left) from this value and expect the result to make sense.

Resources