rr6

Access package-wide variable from within an R6 class


I am currently packaging up an API wrapper in R and found myself in a scenario in which I need to access a package-wide variable from within an R6 class (as it'll be used for a simple string concatenation). Below you can find an exemplification of my class:

#' A class that will need a package-wide variable
#'
#' @export
MyClass <- R6::R6Class(
  "MyClass",
  public = list(
    # This var is a concat between a package-wide variable and a str
    base_url = paste0(.base_url, "me/", "endpoint"),
  )
)

.base_url is declared in my zzz.R file in the following way:

.base_url <- "https://api.coolwebsite.com/v1/"

# Assign var to the environment
.onLoad <- function(libname, pkgname) {
  assign('.base_url', .base_url, envir = parent.env(environment()))
}

Now, when building the package I receive the following error, I do believe there is something I don't fully grasp in the order of evaluation of files when loading a package.

Loading test
 Error in paste0(.base_url, "me/", "endpoint") : 
  object '.base_url' not found

At the moment, the only way I've found to evaluate .base_url before MyClass is to "alter" evaluation order by declaring .base_url in a file that will be evaluated before zzz.R (like constants.R or anything that'll come earlier in alphabetical order).

How can I keep all my package-wide variables in zzz and avoid incurring in the error above?


Solution

  • Answering my own question here as no one has come up with an answer and it might be helpful to people facing the same issue.

    Apparently there are two ways of overriding file order when a package gets attached (more on this here):

    1. @include roxygen tag

    Listing files a function might depend on using @include roxygen tag, will force to load those files before the function gets evaluated, making sure to have all the variables into the namespace at the time of function evaluation.

    #' A class that will need a package-wide variable
    #'
    #' @include zzz.R
    #'
    #' @export
    MyClass <- R6::R6Class(
      # ... All those fancy class methods
    )
    

    This will be reflected by changes in the Collate section of your DESCRIPTION file.

    2. Edit Collate section in DESCRIPTION file

    If not using {roxygen} (but you really should) you can do things by hand and put zzz.R first in the Collate section of your DESCRIPTION file (right after Imports).