Testing if note exists *before* creating it

This arose working though a scenario in a large complex file with @satikusala, trying to manage the issue of not running action code when not needed. He’ll cover this in more detail in a demo at some point, so if not familiar with action code wait for that. But from more seasoned hands, I’ve added a new section to the end of my aTbRef note on create([containerStr, ]nameStr).

The short version is this:

  • create() will not create a note that already exists, but, for either outcome it returns the path of the (created/existing) note.
  • you have code needing to run exactly one time upon new notes that you will create.

How to avoid running such code if the note already exists, given the create() call might get run in all sorts of contexts? For a solution, see:

var:string vTestPath = "/foo/bar/baz";
var:string vTest = $IDString(vTestPath);
var:string vNewPath;
if(vTest==""){
	vNewPath = create(vTestPath);
	// now do tasks only needed once, for new notes
};

[Edit: code changed to reflect an observation below by @satikusala]

The trick here is a non-existent path can’t return an $IDString value, i.e. you get an empty string. The `create() and additional actions are only run if the desired note (path) doesn’t already exist.

This a scenario you will not face in a TBX with only a few tens of notes. But, if you have thousands of notes and they are all running action code, this sort of control pattern can help avoid running unnecessary code and help keep you document running quickly.

If this doesn’t make sense, it will turn up a demo ere long. Meanwhile, those more familiar with action code, and with such a need, can make use of the concept now.

@mwra I don’t think you want $Text=create (vTestPath), I think you just want creat(vTestPath). What you have above will replace the $Text of the note executing the action code with the the vTestPath, which, in most cases I don’t think you want. You don’t want to overwrite you test.

In my case, I’m passing variables, so my code looks like this:

  var vNote=vPrefix+x;
  var vPath=vContainer+vNote;
  var vSource=$Name(this)+":["+date(now).format(l)+";"+document["name"]+"]";
  var:string vNewNote = $IDString(vPath);
  if(vNewNote==""){
     create(vContainer,vNote);
     if(vProto!=""){$Prototype(vPath)=vProto;};
     if(vProto=="Person"){stamp(vNote,"ParsePersonName");};
     if(vSource!=""){$Source(vPath)=vSource;};
  };

I test if the note “x” already exists.
If it doe snot exist, I then create it. I also assign it a prototype, stamp it to parse the name if it uses the person prototype and then populate a source attribute with the name of the note that triggers the creation and the TBX file name. The source helps me track back to why the note was created.

Yes, I’ve now amended the earlier code, where we’d used $Text for testing purposes. Better is to capture the result of create so you can use it in subsequent actions. That variable, vNewPath in my revised code above should be the the same as vTestPath—not least because that’s whet the conditional test does so you could call create() directly and re-use vTestPath if subsequently needed. There’s invariably some scope for approaching this.

1 Like

Of course, this is ideally wrapped up in a function. After that, you only need to write if(exists(thePath)){....} and you’re all set.

1 Like

Yup, that is the way I’m implementing it. Most definitely a key optimizer in my larger file.