Updating tags programatically

Is there a way to use the API to modify content tags? I'm trying to write a pins client which uploads a file and then also applies the correct tags to that file.

2 Likes

Hi @gordon,

Thanks for your post. We don't currently have this functionality available in the public Content management API for RStudio Connect. Have you worked with the experimental content API to programmatically manage content on Connect before? https://docs.rstudio.com/connect/api/#content

I would be interested in hearing more about your use case here. Have you been applying tags manually so far? Is tagging an important part of the deployment process for new content? And is this a one-time programmatic action, or do you need to update tags programmatically over time?

1 Like

I did take a look at the experimental API, but couldn't figure out how to update the tags parameter.

The use case is that we are using pins to store data and want to automatically apply tags to that data based on things like which folder it's in. We have been applying tags manually so far, but we want to do this automatically so that the user who's pinning the data doesn't need to think about it.

Thanks for sharing the use case there! It is definitely helpful to see the types of workflows our users are aiming for!

Do you mind sharing your thoughts on how you expect to specify the tags that you want to set? I.e. what type of interface would you expect for specifying the tag(s) for a given pin? What would you expect to happen if the tag you specify did not exist? This can be tricky with nested tag structures, etc. Are these top level tags you are using, or nested within some other hierarchy? (i.e. you can have tags with the same name in different hierarchies)

Apologies for the barrage of questions there. I'd really love to get a picture of what the "ideal workflow" looks like in your mind, especially since this is a currently nonexistent feature! :slight_smile:

1 Like

Ah, okay so there are basically two api cases here:

Tags for a single piece of content

In this case I think the top level API should require and return a nested list of tags for the piece of content. So if you asked for tags(content) you might get back something like:

list(
  tag1 = list(
    tag2 = "Tom"
    tag3 = "Walter"
  )
  tag2 = "Harry"
)

Then if you wanted to set the different tag2's you would use:

tags(content) <- list(tag2 = "New Harry")
tags(content) <- list(tag1 = list(tag2 = "New Walter"))

Then you could build some convenience functions into the R package which would make it easier to construct the API response where there weren't any duplicated tags. I.e. the user would supply something like:

tags(content) <- list(tag3 = "Walter")
tags(content)$tag3 <- "New Waler"

But you would convert that to the full nested structure before posting it.

tags(content) <- list(tag1 = list(tag3 = "New Waler"))

Navigating tags

I'm not exactly sure how to navigate nested tags programatically, but you might take some inspiration from this folder based API which Neal developed at Crunch: https://github.com/Crunch-io/rcrunch/blob/master/vignettes/projects.Rmd It accomplished a similar job and worked very well.

1 Like

Interesting!! Thanks for the thoughtful overview there! I will definitely take a look at the example you provided (although I have not yet). Just to be clear here, what do the names here represent? tag3 vs. tag1? Is there any meaning there?

1 Like

Oh yes sorry my example makes no sense. I think just replace all the character names with logicals. So a piece of content might be tagged:

list(
  tag1 = list(
    tag2 = TRUE
    tag3 = FALSE
  )
  tag2 = TRUE
)

And on the R package side you could accept either character or logical vectors like this:

# copy tags 
tags(content1) <- tags(content2)

 # apply these subtags
tags(content)$tag1 <- c("tag1", "tag2")

# remove tag2
tags(content)$tag2 <- FALSE

# remove all tags
tags(content) <- FALSE
1 Like

Very interesting! Thanks for sharing! These are some really good thoughts on what an R CLI/SDK for managing tags would look like! This will definitely be super useful as we explore this implementation. Please continue sharing if you have any additional ideas!! And we will keep you updated as we make changes to this functionality!

1 Like