Renaming key attributes without losing values


(Malcolm Coad) #1

Is there any way of renaming key user attributes without losing the values already assigned? I’ve tried renaming the attribute I wish to change by means of the Document Inspector’s User tab, but all the values already filled in disappear. Is there any way of keeping them, perhaps by creating a new attribute and reassigning the list of values, or is the only solution to do this manually in every note? I’ve looked at the Attribute Browser but can’t find a way of doing any of this.


(Mark Anderson) #2

To be clear you’re re-naming a user attribute you’ve already set as a Key Attribute? For me in v7.1.0, if I rename a User Attribute, the entry is updated and the value (as before the renaming) still persists.

But, if you are using an action (agent, stamp, OnAdd, etc.) and you used the old attribute name in your code, you’ll need to review and update the code. Renaming an attribute does not find and update any/all instance of stored code; only Key Attribute tables get updated with the new name.

Other than this it’s not clear from the description why the values are disappearing. Can you post a web link to a file that repeatably shows this problem?


(Malcolm Coad) #3

Hello Mark -

Many thanks for your prompt reply. I am indeed using v.7.1.0 and trying to rename a User attribute. I’ll put a copy of the file in a shared Dropbox folder and send you the link. It’d be great if you could look it over, and any advice you can give would be very much appreciated.

The key attribute I’m trying to change is in the notes in the container Ruiz/Prototypes/Notes (there’s a tab going straight there). The key attributes are set in the Notes prototype. The one I’m trying to change is User/Topic. I want to change this to Keyword. As explained, I’ve tried doing this via the Document Inspector User tab, but the values are lost. They return when I change the name back again. I’ve not tried any other method, via a Stamp or suchlike.

I’m a longtime but fairly superficial user of Tinderbox, now getting to grips with it more fully, and have never delved much under the hood, so I may well be making a rookie mistake or missing something obvious to more experienced eyes.

The Dropbox invitation should reach you shortly by direct email.


(eastgate) #4

I’ve emailed you the solution. Quick summary:

a: define the new attribute.
b: make a temporary agent to copy the values of your old attribute to the new attribute.
c: adjust your prototypes to make the new attribute a Key Attribute where that’s appropriate
d: you’re done. (You could now delete the old attribute, but it’s not doing any harm)


(Mark Anderson) #5

@eastgate - thanks for the cc on that email

Other takeaway points for later readers:

  • You can rename existing attributes but doing so does remove any existing note values set using the old attribute name (explained in the previous post is how to work around the data value side of things.
  • If you do rename an attribute, notes using it as a Key Attribute will update to use the new name.
  • An exception to this is if you are using action code (stamps, rules, agents, etc.) to set your Key Attributes. In that case you will need to review the code and correct the old attribute name manually in the code.

(Malcolm Coad) #6

Many thanks to both. Mark B, your email arrived - very full, perfect. Now to apply it. Such prompt help, very much appreciated.


(Malcolm Coad) #7

Just to say, for the benefit of anyone following this, that the solution worked! Gratitude again, all.


(Galen Menzel) #8

This seems to only be true under the following circumstances:

  1. When the old name starts with a lower-case letter and the new name starts with an upper-case letter.
  2. When the old name starts with an upper-case letter and the new name has a different first character from the old name.

In all other circumstances (e.g., both old and new names begin with a lower-case letter), the rename works fine and values are not lost.

Strange times…

@eastgate I’m assuming you are following this, and I do not need to report this separately.


(Andreas Grimm) #9

@mcoad, could share the eastgate-answer with us?


(Paul Walters) #10

Perhaps this is the answer


(Mark Anderson) #11

As @PaulWalters has pointed out (last post above) the answer to the OP’s solution was given by @eastgate. My advice to anyone currently uncertain about renaming attributes & losing data is to follow that advice.

Discussion up-thread has generated a hanging uncertainty remains as to whether/if you can rename user attributes. Prior to v6, it was certainly the case that changing an attribute name in any way was not possible without creating a new attribute.

Following the re-coding of the app in v6+ it appears it is possible sometimes to rename existing attributes but I’m not sure if that change is accidental or actual design intent. Given @eastgate’s solution above, my hunch is that renaming-with-value-retention is accidental. I’ll look into this off forum and update notes (and confirm here) if I can get a clear answer.


(Paul Walters) #12

Tinderbox does not have an explicit attribute “Rename” function in the Attribute Inspector or anywhere else, so i would conservatively assume any renaming experiments (short of doing informed expert surgery on the source XML) will have unintended results.


(Andreas Grimm) #13

Thanks. But I thought I’d ask anyway, since @eastgate called it “a quick summary” and not the eMail itself - which might contain explanations someone like me could use.


(Mark Anderson) #14

As I was party to that email exchange, there wasn’t anything extra that was significant. I think my aTbRef notes on renaming attributes is wrong - pending clarification from Eastgate. There are two linked issues:

  • whether you can rename and existing attribute (rather than make a new one)
  • if so, are values retained/transferred

I’d suggest we curtail further speculation on this matter until I can report back on Eastgate’s design intent of the app re this task.


(James Fallows) #15

Agree that higher-level explanation should come from Higher Authorities at Eastgate itself.

But in case you were meaning, what’s the simple one-two-three procedure?, I’ve done this a few times myself, and in a very basic way what Mark A and Mark B have been recommending comes down to:

  1. Create a new User Attribute, of the same type as the one you’re wanting it to replace. Eg $Altitude in place of $Elevation, each of them a number attribute. Or $FinalChapterTitle in place of $ChapterTitle, each of them a string.

  2. Create an agent whose query is simply the name of the existing attribute that you want to replace. For instance, if you enter in the query box, when creating the agent, $Elevation or perhaps $Elevation!=0, that will find all the notes that have any value for that attribute. For a string attribute, you’d do $ChapterTitle or $ChapterTitle!="", each of which should give you all items that have any assigned value for that attribute.

  3. Then have the action code for the agent simply assign the values for the old attribute to the new one. For instance, $Altitude=$Elevation or $FinalChapterTitle=$ChapterTitle . The order is obviously important: the new attribute comes first, and is being assigned the value of the second attribute in the expression.

When you’ve done that, you have attributes with the name you want, with identical values of the previous attributes. You can make the new ones into Key Attribs etc. In my experience it takes less than one minute to set this up and do it.

This is probably 100% obvious to you; spelling it out on the chance that someone may read this for whom it’s not yet obvious.


(Mark Anderson) #16

As regards the data you transfer, remember data types:

  • To Boolean, anything except string “0” or number 0 (but not 0.0) will result in a true value.
  • To Number, anything other than integer of decimal strings result in a value of 0; string like “44.” coerce to the equivalent numbers.
  • To String, booleans coerce as strings “true” or “false”; colours coerce as their colour name or hex value; all else as literal string of the source - including URLs. Dates coerce in the format as seen what the Date is displayed in Key Attributes.

If going from String source to list (List or Set) you get one value. Going the other way to a String you get a single semi-colon-concatenated string of all values. Thus a list of “ant”, “bee” and “cow” values would coerce to a single string “ant;bee;cow”


(Sumner Gerard) #17

One of the reputed strengths of Tinderbox is flexibility in changing things around rather than having to think too much about setting up a structure beforehand (incremental formalization).

Shouldn’t renaming an existing attribute be as straightforward for the user as possible?


(Malcolm Coad) #18

@andreas Here’s the full procedure as emailed to me by @eastgate, posted with his blessing:

"As you have seen, simply renaming the attribute won’t copy the old values to the renamed attribute. So, what we want to do is something like the following.

1: make a copy of your file, and tuck that copy away somewhere safe and out of reach.

2: make another copy of your file, and rename it “WORK FILE”. We’re going to work on that copy. If something goes wrong, no big deal — we’ve got the original and can start over. And if something goes wrong with the original, we’ve got another copy, just in case.

3: now, use the Inspector’s User Attribute pane to make a new user attribute named Keyword. $Topic is currently a string; if you want some notes to have multiple keywords, you might want Keyword to be a list or a set. But that’s up to you.

4: Now, we want to copy of values of $Topic to this new attribute. Again, this is easy enough! Let’s make an agent:

Agent: temporary agent
Query: true
Action: $Keyword=$Topic

This is copy the current value of Topic into the Keyword of every note.

5: Now, we have a bunch of notes that use Topic is a Key Attribute. We don’t want to use Topic anymore; we want Keyword instead. So, let’s begin with the prototype note /Prototypes/Notes. Select that note; you’ll see its key attributes in the text pane.

6: Click on the Add Key Attribute button in the upper right-hand corner; it has a “+” for its label. You’ll see a list of key attributes. At the end of this list, add the attribute Keyword. While you’re at it, you could delete the attribute Topic. Click outside the popover to dismiss it.

7: You should be done. Save your copy, and poke around to make sure it’s what you wanted."

Thanks to Mark B for such a full response.

On @galen’s point, both my old and replacement names did begin with upper case but I still lost the content values. It looks as though @mwra is right and there’s a glitch or anomaly in there somewhere. I did the renaming via the Document Inspector’s User tab, not a stamp or the Attributes browser. It would be nice if it were possible to do it there, but @eastgate’s solution worked fine - and provided a great learning opportunity!


(Mark Anderson) #19

From discussion off-forum, I think the view is that design intent is that it should be possible to change existing user attribute names (and data types). But it wasn’t envisaged that data values would be retained.

So whilst values may survive in some cases (as has been reported above), as at v7.1.0 and unless subsequently told otherwise**, users should not expect data values to survive an attribute name/type change.

** Saving such values has been noted as a possible feature request.

I’ll revise my aTbRef article about this.


(eastgate) #20

The operative design criterion is “as simple as it can be, but not simpler.”

The first thing to ask is, why would we want to rename an attribute in the first place? That, in turn, might lead to some indication of how we would prefer to treat values.

One good place to look for examples of renaming in the wild would be to examine some regrettable or regretted attribute names in Tinderbox itself. Let’s do that:

Typos and ambiguities

For example, should the attribute by $Wordcount or $WordCount? The former was the initial choice, but the latter agrees with Tinderbox usage elsewhere. In practice, almost all typos are found right away, so little or nothing is saved by worrying too much about the existing data.

Semantic drift

Over time, the way you use certain attributes may change, and the original name becomes less apt. For example, you might use $MyNumber in a rule as a place to stuff a temporary value – the cost of an expenditure in Euros, which you will presently convert to US dollars. You intend to do this in one place; that’s reasonable. Then you do it again: still reasonable. Two years later, you’re doing it in seventy notes; they’d all be a lot clearer if the attribute was $Euros rather than $MyNumber.

But here, we have real danger. We know a lot of notes use $MyNumber to store Euros, but do some notes use $MyNumber for something else? It could be a Bad Thing to convert those notes without checking first!

Design Polarity

“Typically, most notes are exported. When we don’t want to export a note, we set $HTMLDontExport to true.” That was the design rationale, anyway. It’s been more than a decade since that decision, and whenever I write an expression that depends on this attribute, I get myself tangled up in double negatives: if(!$HTMLDontExport&$HTMLExportChildren(parent)){…}.

So, perhaps we might rename this to $HTMLExport! But here, we really don’t want to copy the current values; we want to invert those values. That’s easy to do for in an agent, of course.

Representation Change

Sometimes, we rename an attribute because we’ve changed the sort of thing the attribute holds. We initially had a string $Topic, and now we want a set of $Topics. We initially had a numeric attribute $TrackLength that held the length of the recording in seconds, but now that we have intervals we might want instead to have the interval $Duration. Here, standard coercion might give us the correct result much or all of the time, but it’s not hard to imagine cases where it doesn’t. (For example, suppose $TrackLength had been measured in fractions of a minute?)

In early versions of Tinderbox, we had separate shapes “right tag” and “left tag”. Later, we changed this to a single shape, “tag”, and used the Boolean $Direction to indicate the orientation. $Direction itself originated with the “leaf” shape and was originally named $LeafDirection. Even today, Tinderbox has to check every file and automatically update these values.


So, it’s not difficult to anticipate cases where automatic conversions are tricky or pernicious. Using a temporary agent is fast and easy; a moderately experienced Tinderboxer can do this in two shakes of a cat’s whisker, and it’s the sort of thing that can encourage users to dip their toes into the world of agents and actions.

That said, I’m not averse to allowing rename to automatically transfer values, applying automatic coercion as needed.