0

I want to execute an overriden static method from the base class without being instantiated.

I want to use an MVC like pattern on an app I'm building and I've created a class named Model that connects to a database and gets the object, it has some static methods that I'm overriding such as the table name (tableName). The problem is that this method must be called from static methods.

From the base class all works like a charm, the problem is when I use other class that extends the base one.

Here's the code:

class Model {

    static get tableName() {
        return this.name;
    }

    static get primaryKey() {
        return "id";
    }

    static get columns() {
        return [];
    }

    static id(id) {
        return new Promise((resolve, reject) => {
            Model.get(Model.primaryKey, id)
            .then(models => {
                resolve(models[0]);
            });
        });
    }

    static get(columnName, value, compareSymbol) {
        return new Promise((resolve, reject) => {
            if (!compareSymbol) {
                compareSymbol = "=";
            }

            let sql = `select * from ${this.tableName}`,
            params = [];

            if (typeof columnName !== "undefined") {
                sql += ` where ${columnName} ${compareSymbol} ?`;
                params = [columnName, value];
            }

            console.log(sql, params);
        });
    }

    constructor(params) {
        this.target = new.target

        for (let name in params) {
            if (Model.primaryKey == name) {
                this[`#${name}`] = params[name];
            } else {
                this.set(name, params[name]);
            }
        }
    }

    set(name, value) {
        if (name != this.target.primaryKey && this.target.columns.indexOf(name) > -1) {
            this[`#${name}`] = value;
        }
    }

    get(name) {
        return this[`#${name}`];
    }

    executeSql(sql, variables) {
        console.log(sql, variables);
    }

    update() {
        let columns = this.target.columns.slice(),
        values = [],
        sql;

        sql = `update ${this.target.tableName} set ${columns.join("=?, ")}=? where ${this.target.primaryKey} = ${this.get(this.target.primaryKey)}`;

        for (let i = 0; i < columns.length; i++) {
            values.push(this.get(columns[i]));
        }

        return this.executeSql(sql, values);
    }
}

// from this line down is other different file

class Directory extends Model {
    static get tableName() {
        return "directories";
    }

    static get columns() {
        return [
            "name",
            "path",
            "recursive"
        ];
    }
}

// shows "from Model" expected "from directories"
Directory.id(2);

// work as expected
let d1 = new Directory({
    id: 1,
    name: "name",
    path: "path",
    recursive: false
});
d1.update();

If called without being instantiated it returns "Model", is there any way to get the overriden value from the base class?

Alexander BC
  • 130
  • 2
  • 10
  • Can you please make a [mcve], including the code that calls `create`? I cannot reproduce the issue, your code works for me. – Bergi Jan 31 '19 at 20:08
  • Are you maybe using a transpiler that doesn't properly support `new.target`? – Bergi Jan 31 '19 at 20:08
  • Instead of using `this.target`, you might as well use `this.constructor` everywhere – Bergi Jan 31 '19 at 20:09
  • new.target works perfectly, @Bergi this.constructor resolves to the extended class? Here is a jsfliddle with all the code https://jsfiddle.net/7f0gturh/ (this is the current code I have) – Alexander BC Jan 31 '19 at 20:30
  • The linked fiddle has a syntax error, and even after fixing that it doesn't log anything (neither expected nor unexpected values). – Bergi Jan 31 '19 at 21:23
  • Here's the correc link, tough modifications were saved on the samew URL... https://jsfiddle.net/qoj45t0p/11/ – Alexander BC Jan 31 '19 at 22:12
  • I'm getting "*update directories …*" and "*insert into directories …*" as expected. What's not working? – Bergi Jan 31 '19 at 22:31
  • 1
    In the `static get` method you explicitly refer to `Model.tableName` not `this.tableName`, is that on purpose? – Bergi Jan 31 '19 at 22:32
  • I'm using Model.tableName on purpose, this.tableName does not exist as this refers to the promise itself. I could set a variable self=this before the promise and use it but it as equally as Model – Alexander BC Jan 31 '19 at 23:59
  • So what exactly is the problem? What is the unexpected output? – Bergi Feb 01 '19 at 05:23
  • Btw, no, `this` does not refer to the promise. To make it refer to the receiver class, [just use an arrow function](https://stackoverflow.com/q/20279484/1048572). – Bergi Feb 01 '19 at 05:24
  • Problem solved, changing the Model to this on all methods worked. It didn't work on the previous tests becouse I was not changing all of them. Thx, btw how can i give you the "mark as answer"? – Alexander BC Feb 01 '19 at 14:26

0 Answers0