Skip to content

Commit

Permalink
Add new blogpost
Browse files Browse the repository at this point in the history
  • Loading branch information
joelnitta committed Jan 11, 2024
1 parent c6429c6 commit e42aac5
Show file tree
Hide file tree
Showing 3 changed files with 533 additions and 0 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
{
"hash": "152291ad15dffa8a6addf906d9880f7d",
"result": {
"markdown": "---\ntitle: \"Documenting blog posts with renv\"\ndescription:\n One solution to the 'ack I can't re-knit my post' problem\ndate: 2024-01-11\ndate-modified: today\nimage: https://i.giphy.com/W69vZGazsH2LDnKCzY.webp\ncitation:\n url: 2024-01-11_using_renv_with_blog\nlang: en\ncategories:\n - R\n - blogging\n - reproducibility\n---\n\n\n\n\n## TL;DR\n\nI show how to use the `renv::use()` function to document the R packages used to write a blogpost.\n\n## Help, I've fallen and I can't re-knit my post!\n\nOne perennial issue with blogging about R^[Technically this applies to blogging about anything that includes running code, but this is a blog about R so that's what you get] is that the blogger may find themselves unable to run the code in a particular post after some time has passed due to package updates that break the code.\nI call this the \"I can't re-knit my post\" problem.\n\nThere have been various solutions proposed to this vexing problem, including:\n\n1. [Freezing post computations using Quarto](https://quarto.org/docs/websites/website-blog.html#freezing-posts)\n2. [Writing the post as a static Markdown file](https://clauswilke.com/blog/2020/09/08/a-blogdown-post-for-the-ages/)\n3. [Using `renv` to maintain one R package library per post](https://www.rostrum.blog/posts/2022-03-15-renv-profiles/)\n\nI think Approach 1 (freezing the post) is the most straightforward solution to prevent unintended knit failures, but that does not document the packages used, so it does not help with actually re-running the code later.\n\nI tried [a variant of Approach 3](https://github.com/djnavarro/refinery) (one `renv` library per post) previously, but found that it was easy to get confused between different `renv` environments, and it ended up being more trouble than it was worth.\n\n## Using `use()`\n\nHere, I suggest a simple solution based on the [`use()` function](https://rstudio.github.io/renv/articles/use.html) from the [`renv` package](https://rstudio.github.io/renv/index.html), as suggested by that package's author, [\\@kevinushey](https://github.com/kevinushey).\nI take the liberty of copying some of the `use()` documentation here (but I recommend you [read the whole thing](https://rstudio.github.io/renv/articles/use.html) anyways)^[I also couldn't help but borrow the vignette title. Thanks [\\@kevinushey](https://github.com/kevinushey)!].\n\n`renv::use()` takes a list of packages and their versions, then:\n\n- Automatically downloads the requested packages\n- Installs the requested packages (plus their recursive package dependencies) to a temporary library path\n- Activates that library path, so that it's used subsequently in the script\n\nBasically, instead of maintaining a per-project package library, it **re-creates the library for a single script^[You might think this means it would take a terribly long time to start up the session each time you work on the script, but thanks to `renv`'s caching mechanism, it actually is quite fast after the first time]**.\n\n## Workflow\n\nFirst, some setup: if you use `renv` for your overall website, I recommend telling `renv` to ignore any scripts in the folder where you store your blog posts, since those will get documented on a per-post basis.\nFor example, if your blog post folder is called `posts`, add `posts` to the `.renvignore` file in the root of your project:\n\n```\nposts\n```\n\nThis allows us to have multiple, independent `renv.lock` files within a single website project without complete chaos.\n\nThe rest of the workflow goes like this:\n\n1. Create blog post, for example, `./posts/2024-01-11_my_post/index.qmd`.\n2. Open that post folder in its own instance of VScode or RStudio (so that your working directory is `./posts/2024-01-11_my_post/`).\n3. Write post, including code chunks.\n4. Run `renv::snapshot()`. This will write `./posts/2024-01-11_my_post/renv.lock`, but **will not modify `.Rprofile`** or create a project library.\n5. Include the line `renv::use(lockfile = \"renv.lock\")` in the setup chunk of your post (or a chunk at the very top with `#| include: false`).\n6. Go back to your main website project and run `quarto render` or `quarto preview` to knit the post. Your post will use the package versions stored in the lockfile for that post.\n7. If you need to update the post, repeat steps 2--4, and render again.\n\n## Example\n\nThis post hasn't used any code yet, so here is some by way of example.\n\n\n::: {.cell}\n\n```{.r .cell-code}\nlibrary(minimal) # my package for testing, which you probably don't have installed\nlibrary(digest)\n\ndigest(pi)\n```\n\n::: {.cell-output .cell-output-stdout}\n```\n[1] \"6f6167522f32e131f999273c788e4930\"\n```\n:::\n:::\n\n\nI have gone through the workflow steps above and added the call to `renv::use()`.\nPlease have a look at the [source code of this blog post](https://github.com/joelnitta/joelnitta-home/tree/main/posts/2024-01-11_using_renv_with_blog/index.qmd) to see how this works.\n\n## Conclusion\n\nI like this approach because we don't actually create multiple `renv` projects, so we can avoid headaches related to project-switching (though you still need to use different working directories).\n\nOne downside is that given enough time, it may no longer be possible to install the R packages at their specified versions again.\nHowever, perhaps this isn't such a problem after all: it means whoever is trying to run your code most likely also cannot install the packages, so your post needs to be updated!\n\nAnother plus is that we can include an [appendix](#reproducibility) at the end of each post linking to the `renv.lock` file so any interested reader can see what package versions were used.\n\nFinally, this should be used in conjunction with the [freeze](https://quarto.org/docs/websites/website-blog.html#freezing-posts) functionality of Quarto to control when each post gets rendered.\n\nHappy blogging!\n\n## Reproducibility {.appendix}\n\n- [Source code](https://github.com/joelnitta/joelnitta-home/tree/main/posts/2024-01-11_using_renv_with_blog/index.qmd)\n- [`renv` lockfile](https://github.com/joelnitta/joelnitta-home/tree/main/posts/2024-01-11_using_renv_with_blog/renv.lock)",
"supporting": [],
"filters": [
"rmarkdown/pagebreak.lua"
],
"includes": {},
"engineDependencies": {},
"preserve": {},
"postProcess": true
}
}
107 changes: 107 additions & 0 deletions posts/2024-01-11_using_renv_with_blog/index.qmd
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
---
title: "Documenting blog posts with renv"
description:
One solution to the 'ack I can't re-knit my post' problem
date: 2024-01-11
date-modified: today
image: https://i.giphy.com/W69vZGazsH2LDnKCzY.webp
citation:
url: 2024-01-11_using_renv_with_blog
lang: en
categories:
- R
- blogging
- reproducibility
---

```{r}
#| label: setup
#| include: false
renv::use(lockfile = "renv.lock")
```

## TL;DR

I show how to use the `renv::use()` function to document the R packages used to write a blogpost.

## Help, I've fallen and I can't re-knit my post!

One perennial issue with blogging about R^[Technically this applies to blogging about anything that includes running code, but this is a blog about R so that's what you get] is that the blogger may find themselves unable to run the code in a particular post after some time has passed due to package updates that break the code.
I call this the "I can't re-knit my post" problem.

There have been various solutions proposed to this vexing problem, including:

1. [Freezing post computations using Quarto](https://quarto.org/docs/websites/website-blog.html#freezing-posts)
2. [Writing the post as a static Markdown file](https://clauswilke.com/blog/2020/09/08/a-blogdown-post-for-the-ages/)
3. [Using `renv` to maintain one R package library per post](https://www.rostrum.blog/posts/2022-03-15-renv-profiles/)

I think Approach 1 (freezing the post) is the most straightforward solution to prevent unintended knit failures, but that does not document the packages used, so it does not help with actually re-running the code later.

I tried [a variant of Approach 3](https://github.com/djnavarro/refinery) (one `renv` library per post) previously, but found that it was easy to get confused between different `renv` environments, and it ended up being more trouble than it was worth.

## Using `use()`

Here, I suggest a simple solution based on the [`use()` function](https://rstudio.github.io/renv/articles/use.html) from the [`renv` package](https://rstudio.github.io/renv/index.html), as suggested by that package's author, [\@kevinushey](https://github.com/kevinushey).
I take the liberty of copying some of the `use()` documentation here (but I recommend you [read the whole thing](https://rstudio.github.io/renv/articles/use.html) anyways)^[I also couldn't help but borrow the vignette title. Thanks [\@kevinushey](https://github.com/kevinushey)!].

`renv::use()` takes a list of packages and their versions, then:

- Automatically downloads the requested packages
- Installs the requested packages (plus their recursive package dependencies) to a temporary library path
- Activates that library path, so that it's used subsequently in the script

Basically, instead of maintaining a per-project package library, it **re-creates the library for a single script^[You might think this means it would take a terribly long time to start up the session each time you work on the script, but thanks to `renv`'s caching mechanism, it actually is quite fast after the first time]**.

## Workflow

First, some setup: if you use `renv` for your overall website, I recommend telling `renv` to ignore any scripts in the folder where you store your blog posts, since those will get documented on a per-post basis.
For example, if your blog post folder is called `posts`, add `posts` to the `.renvignore` file in the root of your project:

```
posts
```

This allows us to have multiple, independent `renv.lock` files within a single website project without complete chaos.

The rest of the workflow goes like this:

1. Create blog post, for example, `./posts/2024-01-11_my_post/index.qmd`.
2. Open that post folder in its own instance of VScode or RStudio (so that your working directory is `./posts/2024-01-11_my_post/`).
3. Write post, including code chunks.
4. Run `renv::snapshot()`. This will write `./posts/2024-01-11_my_post/renv.lock`, but **will not modify `.Rprofile`** or create a project library.
5. Include the line `renv::use(lockfile = "renv.lock")` in the setup chunk of your post (or a chunk at the very top with `#| include: false`).
6. Go back to your main website project and run `quarto render` or `quarto preview` to knit the post. Your post will use the package versions stored in the lockfile for that post.
7. If you need to update the post, repeat steps 2--4, and render again.

## Example

This post hasn't used any code yet, so here is some by way of example.

```{r}
#| label: example
library(minimal) # my package for testing, which you probably don't have installed
library(digest)
digest(pi)
```

I have gone through the workflow steps above and added the call to `renv::use()`.
Please have a look at the [source code of this blog post](https://github.com/joelnitta/joelnitta-home/tree/main/posts/2024-01-11_using_renv_with_blog/index.qmd) to see how this works.

## Conclusion

I like this approach because we don't actually create multiple `renv` projects, so we can avoid headaches related to project-switching (though you still need to use different working directories).

One downside is that given enough time, it may no longer be possible to install the R packages at their specified versions again.
However, perhaps this isn't such a problem after all: it means whoever is trying to run your code most likely also cannot install the packages, so your post needs to be updated!

Another plus is that we can include an [appendix](#reproducibility) at the end of each post linking to the `renv.lock` file so any interested reader can see what package versions were used.

Finally, this should be used in conjunction with the [freeze](https://quarto.org/docs/websites/website-blog.html#freezing-posts) functionality of Quarto to control when each post gets rendered.

Happy blogging!

## Reproducibility {.appendix}

- [Source code](https://github.com/joelnitta/joelnitta-home/tree/main/posts/2024-01-11_using_renv_with_blog/index.qmd)
- [`renv` lockfile](https://github.com/joelnitta/joelnitta-home/tree/main/posts/2024-01-11_using_renv_with_blog/renv.lock)
Loading

0 comments on commit e42aac5

Please sign in to comment.