question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Field validation error when using object reference

See original GitHub issue

Expected behavior

Create item (document) using __ref, when model defined with required: true and without many: true.

Actual behavior

Error occurs when applying an update.

{ [ValidationError: Post validation failed]
  message: 'Post validation failed',
  name: 'ValidationError',
  errors: 
   { category: 
      { [ValidatorError: Path `category` is required.]
        message: 'Path `category` is required.',
        name: 'ValidatorError',
        properties: [Object],
        kind: 'required',
        path: 'category',
        value: undefined } },
  model: 'Post',
  data: 
   { name: 'A draft post',
     category: 'keystone',
     __doc: { _id: 574e9e74a7f5369c84ac372c, name: 'A draft post' } } }

Steps to reproduce the behavior

Apply update using models and update script below.

// models/Post.js

var keystone = require('keystone');
var Types = keystone.Field.Types;

var Post = new keystone.List('Post', {
    autokey: { path: 'slug', from: 'name', unique: true }
});

Post.add({
    name: { type: String, required: true },
    category: {
        type: Types.Relationship,
        ref: 'PostCategory',
        initial: true,
        required: true
    }
});

Post.register();
// models/PostCategory.js

var keystone = require('keystone');

var PostCategory = new keystone.List('PostCategory', {
    autokey: { from: 'name', path: 'key', unique: true }
});

PostCategory.add({
    name: { type: String, required: true }
});

PostCategory.relationship({ ref: 'Post', path: 'category' });
PostCategory.register();
// updates/0.0.1.js

exports.create = {

    PostCategory: [{
        name: 'Keystone JS',
        __ref: 'keystone'
    }],

    Post: [{
        name: 'A draft post',
        category: 'keystone'
    }]

};

Issue Analytics

  • State:open
  • Created 7 years ago
  • Comments:10 (4 by maintainers)

github_iconTop GitHub Comments

2reactions
stevenkasparcommented, Dec 4, 2017

Here is one way to handle it, but it requires changing data a little bit - it isn’t very dynamic so it won’t handle child refs but it could probably be improved easy enough

const keystone = require('keystone')
const moment = require('moment')

const DATA = {
  User: [
    { 'name.first': 'Admin', 'name.last': 'User', 'email': 'admin@abzu.io', 'password': 'password', 'is_admin': true },
    { 'name.first': 'Jack', 'name.last': 'Smith', 'email': 'stevenkaspar+swjacksmith@abzu.io', 'password': 'password', 'is_admin': false, },
  ],
  Visit: [
    {
      'REF__user': {ref: 'User', find: {email: 'stevenkaspar+swjacksmith@abzu.io'}},
      'checkin_date': moment().subtract(10, 'days').toDate(),
    }
  ],
  //
  Invoice: [
    {
      'REF__visit':    {ref: 'Visit', find: async () => {
        let user = keystone.list('User').model.findOne({email: 'stevenkaspar+swjacksmith@abzu.io'})
        return {
          user: user._id
        }
      }},
      'date': moment().subtract(9, 'days').toDate(),
      'amount': 1000.00,
    }
  ],
};

async function create (keystone_list, data) {
  let List = keystone.list(keystone_list)
  let created_items = []
  for(let item of data[keystone_list]){
    for(let key in item){
      // use 'REF__' to define fields
      if(/^REF__/i.test(key)){
        // remove 'REF__' and use as mongoose field name
        let keystone_field = key.replace(/^REF__/i, '')
        // allows for many: true
        if(Array.isArray(item[key])){
          item[keystone_field] = []
          for(let many_item of item[key]){
            let ref_item = await keystone.list(many_item.ref).model.findOne(await many_item.find)
            if(ref_item === null) throw new Error(`${many_item.ref} find \n${JSON.stringify(many_item.find, null, '  ')}\n is null`)
            item[keystone_field].push(ref_item._id)
          }
        }
        else {
          let ref_item = await keystone.list(item[key].ref).model.findOne(await item[key].find)
          if(ref_item === null) throw new Error(`${item[key].ref} find \n${JSON.stringify(item[key].find, null, '  ')}\n is null`)
          item[keystone_field] = ref_item._id
        }
        // delete the 'REF__xx' key so we don't keep that on the document
        delete item[key]
      }
    }
    let new_item = new List.model(item)
    await new_item.save()
    created_items.push(new_item)
  }
  return created_items
}

exports = module.exports = async function (done) {
  for(let model in DATA){
    try {
      await create(model, DATA)
    }
    catch(e){
      done(e)
    }
  }
  done()
};
1reaction
Novinycommented, Mar 29, 2017

The root cause is likely to be non-trivial to solve, so for anyone needing to press forward, a possible workaround is to have two update scripts, the first of which adds items to be depended upon, the second as a function that retrieves the items by their reference, before saving the new items.

Read more comments on GitHub >

github_iconTop Results From Across the Web

An object reference is required for the non-static field, method ...
I have tried this method as static but i am getting this error Keyword 'this' is not valid in a static property, static...
Read more >
Error 'You have reached the maximum number of 15 object ...
This error occurs because you have reached the limit of spanning relationships (also known as cross-object reference) per object. What is a ...
Read more >
GridView - The "Object reference not set to an instance of ...
Get validation error on Memo field when attempting to remove all data from column. This only occurs on Memo columns that have had...
Read more >
Model instance reference - Django documentation
fields or Meta.exclude ). Doing so will raise a ValueError because the validation error won't be able to be associated with the excluded ......
Read more >
Validation Errors when saving new Validation rule
Reaching 10 reference on object · What is the meaning of this message about reference limits in formula fields? · You have reached...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found