Reputation: 1055
I have been working on an ORM-like method of handling my models in a Node.JS app, and I am satisfied with how it works; however, I am wondering if there is a better way to handle resetting the prototype of a constructor function.
The behavior I want is something like this:
function Person(data) {
for (const key in data) {
this[key] = data[key]
}
}
// setting methods and so on here
Person.findAll() // returns a list of all persons from the db
Person.findOne(id) // returns a person at that ID
const self = new Person(data) // creating a person object
self.save() // saves that object in the db
self.update(data) // updates person object
self.addFriend(id) // creates a record adding the given id as a friend
There are methods on the constructor Person
that have access to all Person
records, while each instance of Person
has methods that affect just that one record. I'm managing this like so:
const utils = (tablename) => ({
findAll: () => dbHandler(`SELECT * FROM ${tablename}`),
findOne: id => dbHandler(`SELECT * FROM ${tablename} WHERE id = $1`, [id]),
// etc
})
Object.setPrototypeOf(Person, utils('people'));
.setPrototypeOf
isn't the best method to use; it's not particularly performant. I'm wondering if there is a better way to handle a use case like this -- for example, is there anything in the es6 class spec that would handle this? (Extending classes isn't quite what I'm looking for; the distinction between Person.findAll()
and self.update(data)
is important to me, and I would like the util methods to be on the constructor itself.)
Edit: Shoutout to Bergi below for the solution ("just use Object.assign
")... here's a little demo:
const dbHandler = (string, arr) => console.log(string, arr)
function Person(data) {
for (const key in data) {
this[key] = data[key]
}
}
const utils = (tablename) => ({
findAll: () => dbHandler(`SELECT * FROM ${tablename}`),
findOne: id => dbHandler(`SELECT * FROM ${tablename} WHERE id = $1`, [id]),
// etc
})
Object.assign(Person, utils('people'));
Person.prototype.save = function() {
console.log(`Saving person with data ${JSON.stringify(this)} to a totally real database`)
}
Person.findAll()
Person.findOne(1)
const self = new Person({
name: 'j',
class: 'wizard'
})
self.save()
Upvotes: 2
Views: 83
Reputation: 664513
There's no reason to involve any inheritance here (and setting the prototype of a constructor function so that it no longer inherits from Function.prototype
is really weird). Just assign the static methods as properties of the Person
constructor object:
Object.assign(Person, utils('people'));
This has the same effect as
function createUtils(obj, tablename) {
obj.findAll = () => dbHandler(`SELECT * FROM ${tablename}`);
obj.findOne = id => dbHandler(`SELECT * FROM ${tablename} WHERE id = $1`, [id]);
// etc
}
createUtils(Person, 'people');
Upvotes: 2