Call Project Scripts from Another Project

810 Views Asked by At

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.

2

There are 2 best solutions below

0
On

I had the same issue, and I could resolve it with

here::i_am("path_to_script")
source("path_to_script")

See here package website for details. https://cran.r-project.org/web/packages/here/vignettes/here.html

1
On

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 replacing source calls with calls to box::use. The reason is that ‘box’ provides a module system rather than individual helper functions; hence, box::file etc. 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.R script would look as follows:

box::use(
    ./assumptions[...],
    ./project_env[...],
    ./assumptions[...],
    ./selected_assumptions[...],
    ./output[...],
    ./run_scenarios[...],
)

Where:

  • Module names are unquoted
  • ./… 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$DEFAULT will 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; and box::file('some_file') will return the absolute path of some_file nested inside the module (again, for more details see the vignette linked above).

Lastly, to execute Launch.R outside your project, with the above changes, you can simply run e.g. Rscript path/to/Launch.R and this will work. Alternatively, you can also treat Launch.R as a module and load it via box::use. To do this from outside the project, you’ll need to configure ‘box’ search path via the box.path option. Afterwards, you can use the module via an absolute import directive (in contrast to the previous local, relative import directives):

box::use(projectname/Launch)
  • projectname here would be the folder name of the folder that contains your Launch.R script, and the box.path option needs to include the path to its parent directory.