I'm building an RStudio project (Project 2) where I would like to access certain scripts that are contained within another already-built RStudio project (Project 1). Project 1 contains various scripts, some of which reference one another through source() calls. Is there any way to achieve this? I originally thought that by using here::here() or box::file() in Project 1 could facilitate this, however I realized that both of those functions will reference the working directory of Project 2 as opposed to that of Project 1.
For example, let's say Project 1 contains the following file structure:
> list.files(withr::with_dir("./Project_1", getwd()))
[1] "assumptions.R" "launch.R" "output.R"
[4] "project_env.R" "renv" "renv.lock"
[7] "run_scenarios.R" "Project_1.Rproj" "sample_script_1.R"
[10] "sample_script_2.R" "selected_assumptions.R"
And Launch.R is the script that launches code for all of the remaining scripts (code below).
Launch.R
source("assumptions.R")
source("project_env.R")
project_env$launch_mode = project_env$scenario_toggle$DEFAULT
source("assumptions.R")
source("selected_assumptions.R")
source("output.R")
source("run_scenarios.R")
Is there any way to execute the Launch.R script from outside of Project 1? Because of the way Project 1's scripts are tied together, if I try to execute Launch.R from anywhere outside of the project, I get errors as soon as it tries to execute the source("assumptions.R") command.
Any help would be much appreciated.
To make
box::file()return the current script’s directory path rather than the current working directory, you’ll need to load the script as a module. At its most basic, this means replacingsourcecalls with calls tobox::use. The reason is that ‘box’ provides a module system rather than individual helper functions; hence,box::fileetc. assume that they are being called in the context of a module. The ‘box’ package vignette gives further information.As an example of the usage, with ‘box’ modules your
Launch.Rscript would look as follows:Where:
./…signifies that this is a local, relative module name (rather than a package, or globally installed module which is searched differently)[...]means: attach all names defined inside the module; by default, ‘box’ attaches no exports when loading a module. Attaching isn’t done by default because it’s not generally recommended.Please also note that each module has its own scope, just like R packages. Thus, the statement
project_env$launch_mode = project_env$scenario_toggle$DEFAULTwill have no effect in the loaded modules. To make a module see variables in the calling code, you need to pass them explicitly into the module.With these changes, a
box::file()call inside one of the modules will return the path to that module’s directory; andbox::file('some_file')will return the absolute path ofsome_filenested inside the module (again, for more details see the vignette linked above).Lastly, to execute
Launch.Routside your project, with the above changes, you can simply run e.g.Rscript path/to/Launch.Rand this will work. Alternatively, you can also treatLaunch.Ras a module and load it viabox::use. To do this from outside the project, you’ll need to configure ‘box’ search path via thebox.pathoption. Afterwards, you can use the module via an absolute import directive (in contrast to the previous local, relative import directives):projectnamehere would be the folder name of the folder that contains yourLaunch.Rscript, and thebox.pathoption needs to include the path to its parent directory.