Skip to content

Can't add or modify a value during $beforeUpdate using upsertGraph #2233

@umutuzgur

Description

@umutuzgur

We are trying to push some of calculated logic into the models using instance hooks, there is a case of encryption and decryption as well. This was working correctly with objection 1 but started showing a different behavior with objection 3. The problem is that since objection is doing a diff right before $beforeUpdate is invoked, the values changed in the function don't get picked up as a part of the propsToUpdate and they are not executed in the sql query. I tried to bypass this or somehow tried to change this value. The only thing that work was iterating over $$omitFromDatabaseJson and making sure that the field I want updated is not in this array. It would be great to have an UpsertGraphOptions to skip the diff check. The use case for us is just to update a graph

The code relevant is here

node.obj.$omitFromDatabaseJson(difference(allProps, propsToUpdate));

let Model

try {
  Model = require('./').Model
} catch (err) {
  Model = require('objection').Model
}

const Knex = require('knex')
const chai = require('chai')

async function main () {
  await createSchema()
  const item = { multiplier: 1 }
  // The random value will get modified in $beforeInsert
  const returned = await Item.query().insertGraphAndFetch(item)

  // The random value won't be persisted into the DB
  const newGeneratedRandom = await Item.query().upsertGraphAndFetch({ ...returned, multiplier: 200 })

  chai.expect(newGeneratedRandom.random).to.not.equal(returned.random)
}

/// ////////////////////////////////////////////////////////////
// Database
/// ////////////////////////////////////////////////////////////
const knex = Knex({
  client: 'sqlite3',
  useNullAsDefault: true,
  debug: false,
  connection: {
    filename: ':memory:',
  },
})

Model.knex(knex)

/// ////////////////////////////////////////////////////////////
// Models
/// ////////////////////////////////////////////////////////////

class Item extends Model {
  static get tableName () {
    return 'item'
  }

  $beforeInsert () {
    this.random = Math.ceil(Math.random() * this.multiplier)
  }

  $beforeUpdate () {
    this.random = Math.ceil(Math.random() * this.multiplier)
  }
}

/// ////////////////////////////////////////////////////////////
// Schema
/// ////////////////////////////////////////////////////////////

async function createSchema () {
  await knex.schema
    .dropTableIfExists('item')

  await knex.schema
    .createTable('item', table => {
      table.increments('id').primary()
      table.integer('multiplier')
      table.integer('random')
    })
}

main()
  .then(() => {
    console.log('success')
    return knex.destroy()
  })
  .catch(err => {
    console.error(err)
    return knex.destroy()
  })

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions