Last active
October 12, 2022 15:10
-
-
Save lmuntaner/8f52ee13737aff93bfd997e3e9b76dce to your computer and use it in GitHub Desktop.
A Popular Example of Metaprogramming: ORMs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// 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