Search code examples
rknitrquarto

child can't access objects from parent with knitr::knit_child in Posit Connect


I'm collecting data and creating some figures in a document, let's call it main.qmd. Then, using a loop over knitr::knit_child on another document, say sub.qmd, using data defined in main.qmd, I create additional figures. This works fine when rendering in Posit Workbench.

However, when I publish the results to Posit Connect it fails: sub.qmd can't access values created in main.qmd.

What I've done so far:

  1. Using environment() both files seem to be in the same environment (R_GlobalEnv), so there doesn't seem to be a scoping issue (?). I've created an environment in main.qmd with the object and passed that environment to knit_child. No luck.

  2. I've written to a database from main.qmd and tried reading the data from sub.qmd. Here something very strange is happening: an object (a) created and saved in main.qmd (saved by DBI::dbWriteTable(con, "a", data.frame(a = a))) shows up from a call to DBI::dbListTables(con) in sub.qmd, but when I try reading a from the table (DBI::dbReadTable(con, "a")$a) the rendering fails on Connect.

  3. I've tried creating a pin using the pins-package. The result is equivalent to that in 2.

  4. I've tried saving the data as a.rds in main.qmd and reading from sub.qmd. Again, as in 2.

What is happening, and how can I access objects created in main.qmd in sub.qmd?

Reprex (no saving):

main.qmd:

## Main

This is from the main document

## Sub

```{r}
#| results: asis
for (i in c(1,2)) {
  res <- knitr::knit_child("sub.qmd", quiet = TRUE)
  cat(res, sep = "\n")
}
```

sub.qmd:

```{r}
print(paste("sub:", i))
```

Minimal, reproducable example 2 (saving/reading using .rds).

In the example, file.exists("a.rds") is TRUE, but readRDS("a.rds") throws an error...

main.qmd:

## Main

This is from the main document:
```{r}
a <- 1
saveRDS(a, "a.rds")
```

## Sub

```{r}
#| results: asis
cat(
  knitr::knit_child("sub.qmd", quiet = TRUE)
)
```

sub.qmd:

This is from the sub document:

```{r}
file.exists("a.rds")
# a <- readRDS("a.rds")
# print(a)
```

Solution

  • When publishing multiple .qmd-files to connect, it seems to run all files in arbitrary order. If one of the files is intended as a child document and use variables that are only defined in the main script, then the deployment will fail.

    To solve this problem, you can gracefully terminate the render if quarto attempts to render the child document as a standalone file. Assuming variable_name is defined in the main script:

    if (!exists("variable_name")) {
      knitr::knit_exit()
    }
    

    This should let you deploy all the files and it should work as intended.