kasvith / express-mongo-jwt-boilerplate

Express Mongo JsonWebToken boilerplate

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Move Schema.method transform to external file

d0peCode opened this issue · comments

I want to move methods from this code:

adminSchema.method({
  transform () {
    const transformed = {}
    const fields = ['id', 'name', 'email', 'createdAt']
    fields.forEach((field) => { transformed[field] = this[field] })
    return transformed
  },

  passwordMatches (password) {
    return bcrypt.compareSync(password, this.password)
  }
})

to external files. That's because I'm using transform also in second model and most of the code is just repeated. Perfect solution would be to create property with fields array then assign transform method to required function in which I would use .this keyword to access fields.

//user.model.js
const transformFields = require('./utils/transformFields.js')
...

userSchema.method({
  fields: ['id', 'name', 'email', 'createdAt'],
  transform: transformFields

//transformFields.js
function transform() {

    const transformed = {}

    this.fields.forEach((field) => {
      transformed[field] = this[field]
    })

    return transformed
  },

Unfortunetally when I call register enpoint above code is giving me some weird response:

{
"message": "schema.methods[method][k].bind is not a function",
"errors": {}
}

I don't know what does it mean, maybe schema.method({}) can contain only functions, not properties like fields array. I tried to simplify above to just this:

userSchema.method({
  fields: ['id', 'name', 'email', 'createdAt'],
  transform: function () {
    const transformed = {}

    this.fields.forEach((field) => {
      transformed[field] = this[field]
    })

    return transformed
  },

in order to check if it's problem with requiring external method but above is also giving me same response when register endpoint is called.

Yes, but maybe in the future admin can have more fields that need to be shown on requests.
So I think its better to keep them separate as both models can have different attributes need to be shown

@kasvith,

maybe in the future admin can have more fields that need to be shown on requests.

but this code

const transformed = {}

this.fields.forEach((field) => {
  transformed[field] = this[field]
})

return transformed

will be repeated in every model. Everything what change is

const fields = ['id', 'name', 'email', 'createdAt']

that's why I wanted to declare fields as a property in method({ here so I could extract first snippet from this post to external function and use .this.

{
    "message": "schema.methods[method][k].bind is not a function",
    "errors": {}
}

This comes because mongoose will not allow you to bind non-methods into the schema. We would need to figure out a way to do that in that case.

Unfortunately, im bit busy these days. You can carry on work. I will give a shot when i got time :)

This comes because mongoose will not allow you to bind non-methods into the schema.

That's bad :/. I could declare fields as just const in file scope but then I'll not be able to access it with .this from method.

The only solution I see is to nest function in transform method. I'll try it and add commit to current #23 PR.

This is no longed neccessary as I changed

const transformed = {}

this.fields.forEach((field) => {
  transformed[field] = this[field]
})

return transformed

to

fields.forEach(field => { transformed[field] = this[field] })
return transformed

so now it's just one line and extracting just one or two line/s to external function would be overkill IMO.