p.g.l.hall
p.g.l.hall

Reputation: 1961

Sequelize - include getter returns in plain object

I have a Sequelize class defined with a few virtual fields defined as follows:

class Post extend Sequelize.Model {
  get age () {
    return duration(this.get('createdAt'), new Date()).days
  }
}

(For brevity I've skipped the actual DB fields)

I'm running an Express app, I want these virtual fields to be sent to the client. When I call post.get({ plain: true }) only the "real" DB fields are passed through. I get something like this:

{"createdAt": "2019-03-05T09:16:50.391Z"}

What's the best way of making the response more like this instead?:

{"createdAt": "2019-03-07T09:16:50.391Z", "age": 3}

Upvotes: 2

Views: 1882

Answers (2)

p.g.l.hall
p.g.l.hall

Reputation: 1961

The solution I ended up going with was to declare the getter explicitly in the options, similar to KenOn10's suggestion, but in ES6 syntax. Here's the finished solution:

class Post extend Sequelize.Model {

  static init (sequelize, DataTypes) {
    return super.init(
      'age': {
        type: DataTypes.VIRTUAL,
        get: function () { return this.getAge() }
      }
    }, { sequelize }
  }

  getAge () {
    return duration(this.get('createdAt'), new Date()).days
  }
}

A couple of things to note though:

  • I've changed the getter function to an ordinary function called getAge(), because setting the get property in the schema also creates it as a getter. Therefore, if you call the getter within that function, it goes into a recursive loop and fills up the stack.
  • The get option needs to be defined as a full function, because arrow functions don't have their own this context.

Upvotes: 1

KenOn10
KenOn10

Reputation: 1968

Is there a reason to extend Model? Using the getterMethods property seems to do what you ask. For example:

sequelizeDB.define('my_printer_table',
  {
    printer_code    : {type: Sequelize.STRING,primaryKey: true},
    printer_name    : Sequelize.STRING
  },
  {
  getterMethods: {
    description() {
      return this.printer_code + ' ' + this.printer_name
    }
  }
});

Then, printer.get() results in:

Object {description: "ABC ABC Printing", printer_code: "ABC", printer_name: "ABC Printing"}

Upvotes: 2

Related Questions