Skip to content

Instantly share code, notes, and snippets.

@lmuntaner
Last active October 12, 2022 15:10
Show Gist options
  • Save lmuntaner/8f52ee13737aff93bfd997e3e9b76dce to your computer and use it in GitHub Desktop.
Save lmuntaner/8f52ee13737aff93bfd997e3e9b76dce to your computer and use it in GitHub Desktop.
A Popular Example of Metaprogramming: ORMs
// Used in the article: https://www.gimtec.io/articles/metraprogramming-example-orm/
const pg = require('pg');
/**
* ORM Setup with metaprogramming
*/
const define = async (dbUrl, table) => {
try {
const getTableSchema = (table) => `select * from INFORMATION_SCHEMA.COLUMNS where TABLE_NAME='${table}';`;
const client = new pg.Client(dbUrl);
let isConnected = false;
const connectClient = () => {
if (!isConnected) {
client.connect();
isConnected = true;
}
}
connectClient();
const schema = await client.query(getTableSchema(table));
const rows = schema.rows.map(({ column_name }) => column_name);
const Model = function (attrs) {
rows.forEach(row => {
this[row] = attrs[row];
});
}
const createGetBy = (prop) => {
Model[`getBy${prop.charAt(0).toUpperCase() + prop.slice(1)}`] = async function (value) {
connectClient();
const result = await client.query(`select * from ${table} where ${prop} = ${value}`);
return new Model(result.rows[0]);
}
}
Model.getAll = async function () {
connectClient();
const result = await client.query(`select * from ${table};`);
return result.rows.map((row) => new Model(row));
}
Model.close = function() {
client.end();
}
rows.forEach(createGetBy);
return Model;
} catch (e) {
console.log('in da define error');
console.log(e);
}
};
/**
* ORM usage examples.
*/
const dbUrl = 'postgres://some-url';
const userTest = async () => {
// const User = define(dbUrl, 'users', ['email', 'id', 'name']);
try {
const User = await define(dbUrl, 'users');
const users = await User.getAll();
console.log("USERS:")
console.log(users);
const user = await User.getById(10);
console.log("ONE USER:")
console.log(user);
User.close();
} catch (e) {
console.log('in da error');
console.log(e);
User.close();
} finally {
}
};
userTest();
const postTest = async () => {
// const Post = define(dbUrl, 'posts', ['id', 'user_id', 'title', 'content']);
const Post = await define(dbUrl, 'posts');
try {
const posts = await Post.getAll();
console.log("POSTS:")
console.log(posts);
const post1 = await Post.getById(1);
console.log("ONE POST:");
console.log(post1);
const postsUser = await Post.getByUser_id(11);
console.log("ONE POST:");
console.log(postsUser);
} catch (e) {
console.log('in da error');
console.log(e);
} finally {
Post.close();
}
};
postTest();
/**
* Utils used to setup the database for testing purposes:
*/
const clearTable = 'DELETE FROM users;';
const createUserTable = 'CREATE TABLE users (email varchar, id integer, name varchar);';
const createPostTable = 'CREATE TABLE posts (id integer, user_id integer, title varchar, content varchar);';
const manageTable = () => {
const client = new pg.Client(dbUrl);
const insertUserQuery = (user) => {
return `insert into users (email, id, name) values ('${user.email}', ${user.id}, '${user.name}')`;
};
const insertPostQuery = (post) => {
return `insert into posts (id, user_id, title, content) values (${post.id}, ${post.userId}, '${post.title}', '${post.content}')`;
};
client.connect();
// client.query(insertUserQuery({
// email: '[email protected]',
// id: 10,
// name: 'Amy',
// }))
// client.query(insertPostQuery({
// id: 2,
// title: 'Test Post 2',
// userId: 11,
// content: 'This is a test post',
// }))
client.query(getTableSchema('users'))
.then((data) => {
console.log(data.rows.map((row) => row.column_name));
client.end();
});
};
// manageTable();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment