Allow alabaster applications to divert to a different saving generic instead of saveObject.

altSaveObject(...)

altSaveObjectFunction(generic)

Arguments

...

Further arguments to pass to saveObject or an equivalent generic.

generic

Generic function that can serve as a drop-in replacement for saveObject.

Value

For altSaveObject, files are created at the specified location, see saveObject for details.

For altSaveObjectFunction, the alternative generic (if any) is returned if generic is missing. If generic is provided, it is used to define the alternative, and the previous alternative is returned.

Details

By default, altSaveObject is just a wrapper around saveObject. However, if altSaveObjectFunction is called, altSaveObject calls the replacement generic instead. This allows alabaster applications to inject wholesale or class-specific customizations into the saving process, e.g., to save more metadata whenever an instance of a particular class is encountered. Developers of alabaster extensions should use altSaveObject to save child objects when implementing saveObject methods, to ensure that application-specific customizations are respected for the children.

To motivate the use of altSaveObject, consider the following scenario.

  1. We have created a staging method for class X, defined for the saveObject generic.

  2. An alabaster application Y requires the addition of some custom metadata during the staging process for X. It defines an alternative staging generic saveObject2 that, upon encountering an instance of X, redirects to an application-specific method (i.e., saveObject2,X-method). For example, the saveObject2 method for X could call X's saveObject method and add the necessary metadata to the result.

  3. When operating in the context of application Y, the saveObject2 generic is used to set altSaveObjectFunction. Any calls to altSaveObject in Y's context will subsequently call saveObject2.

  4. So, when writing a saveObject method for any objects that might contain an instance of X as a child, we call altSaveObject on that X object instead of directly using saveObject. This ensures that, if a child instance of X is encountered and we are operating in the context of application Y, we correctly call saveObject2 and then ultimately the application-specific method.

The application-specific generic is free to do anything it wants as long as the custom representation is understood by the application-specific reader in altReadObject. However, it is usually most convenient to re-use the existing representations created by saveObject. This means that any customizations should not interfere with the validity of those representations, as defined by the takane specifications and enforced by validateObject. We recommend that any customizations should manifest as new files starting with an underscore, as this will not interfere by any takane file specification.

Author

Aaron Lun

Examples

old <- altSaveObjectFunction()

# Creating a new generic for demonstration purposes:
setGeneric("superSaveObject", function(x, path, ...)
    standardGeneric("superSaveObject"))
#> [1] "superSaveObject"

setMethod("superSaveObject", "ANY", function(x, path, ...) {
    print("Falling back to the base method!")
    saveObject(x, path, ...)
})

altSaveObjectFunction(superSaveObject)

# Staging an example DataFrame. This should print our message.
library(S4Vectors)
df <- DataFrame(A=1:10, B=LETTERS[1:10])
tmp <- tempfile()
altSaveObject(df, tmp)
#> [1] "Falling back to the base method!"

# Restoring the old loader:
altSaveObjectFunction(old)