You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
One of the requirements I have for most of my applications using session management is to customize the location where session files are stored. In my presentation at the conference I showed a simple example where the application will store session specific data in the user's linux home directory. Using the example app in this repo, I found a way to customize the location for saving session bookmarks. See below for my notes on my journey. But the bigger question I have is if Shiny could allow for this customization directly?
Default saving mechanism
shiny has an internal function called saveShinySaveState which controls the actual writing of input values and optionally any values flagged by the user to save. One dynamic piece of this is pulling the value of a specific shiny option called save.interface. The value of this option depends on the execution environment:
When a shiny app is executed on shiny server, this option is set to be a custom function as seen in the shiny server source code here. The parameters are id (the unique hash id given to the bookmark) and callback (basically how the function registers itself with a shiny session object R6 method called doBookmark ). The shiny-server code is hardcoding various options for the directories of all bookmarks and app-specific bookmarks.
When a shiny app is executed inside RStudio itself (or any general R session), the save.interface option is set to NULL. In that case, a customized version of the saving interface function called saveInterfaceLocal is swapped in dynamically. This function is configured to only save the bookmarks in a sub-directory of the app itself.
Tricking default behavior
In both of the cases above, there is no customization allowed for the location of saving bookmarks. At first I tried hacking around and overriding specific R6 methods and functions to no avail. We needed a way to define our own version of two key options: The aforementioned save.interface and a corresponding load.interface function, each of which need to have the same set of function inputs (id and callback). But how can we pass in custom parameters, such as the user ID of the user executing the app, and a new storage location? The answer is setting custom options via shinyOptions, which is like a shiny-aware version of typical options specifications. Instead of letting shiny-server define the option for us, we can override the options ourselves within the application. We can also set arbitrary options that can be used to pass key information to our custom functions:
Set the user ID of the logged-in user as an option. My usual mechanism to dynamically grab the user ID is a custom reactive that is dynamic to the execution environment
# capture the user ID, set to me if not availableuser<- reactive({
if(!is.null(session$user)) {
my_user<-session$user
} else {
my_user<- Sys.getenv("USER")
}
shinyOptions(user=my_user)
return(my_user)
})
# force execution of user reactive
observe({
user()
})
Set the directory name for saving application settings (can be placed anywhere in server-side processing, no need for a reactive version):
# set file-system options for saving session directory path
shinyOptions(session_dir=".shinysessions")
Define our custom functions for saving and loading interface, and set the appropriate options:
saveInterfaceLocal<-function(id, callback) {
# user ID associated with the app executionuser<- getShinyOption("user")
#directory name for the app's storage locationsession_dir<- getShinyOption("session_dir")
stateDir<- file.path("/home", user, session_dir, "shiny_bookmarks", id)
if (!shiny:::dirExists(stateDir))
dir.create(stateDir, recursive=TRUE)
callback(stateDir)
}
shinyOptions(save.interface=saveInterfaceLocal)
loadInterfaceLocal<-function(id, callback) {
# user ID associated with the app executionuser<- getShinyOption("user")
#directory name for the app's storage locationsession_dir<- getShinyOption("session_dir")
stateDir<- file.path("/home", user, session_dir, "shiny_bookmarks", id)
callback(stateDir)
}
shinyOptions(load.interface=loadInterfaceLocal)
Once all of these have been set up correctly, everything included in shiny for saving and restoring bookmarks will just work and no other modifications are necessary.
The text was updated successfully, but these errors were encountered:
One of the requirements I have for most of my applications using session management is to customize the location where session files are stored. In my presentation at the conference I showed a simple example where the application will store session specific data in the user's linux home directory. Using the example app in this repo, I found a way to customize the location for saving session bookmarks. See below for my notes on my journey. But the bigger question I have is if Shiny could allow for this customization directly?
Default saving mechanism
shiny
has an internal function calledsaveShinySaveState
which controls the actual writing of input values and optionally any values flagged by the user to save. One dynamic piece of this is pulling the value of a specific shiny option calledsave.interface
. The value of this option depends on the execution environment:id
(the unique hash id given to the bookmark) andcallback
(basically how the function registers itself with a shiny session object R6 method calleddoBookmark
). The shiny-server code is hardcoding various options for the directories of all bookmarks and app-specific bookmarks.save.interface
option is set to NULL. In that case, a customized version of the saving interface function calledsaveInterfaceLocal
is swapped in dynamically. This function is configured to only save the bookmarks in a sub-directory of the app itself.Tricking default behavior
In both of the cases above, there is no customization allowed for the location of saving bookmarks. At first I tried hacking around and overriding specific R6 methods and functions to no avail. We needed a way to define our own version of two key options: The aforementioned
save.interface
and a correspondingload.interface
function, each of which need to have the same set of function inputs (id
andcallback
). But how can we pass in custom parameters, such as the user ID of the user executing the app, and a new storage location? The answer is setting custom options viashinyOptions
, which is like a shiny-aware version of typicaloptions
specifications. Instead of letting shiny-server define the option for us, we can override the options ourselves within the application. We can also set arbitrary options that can be used to pass key information to our custom functions:Once all of these have been set up correctly, everything included in
shiny
for saving and restoring bookmarks will just work and no other modifications are necessary.The text was updated successfully, but these errors were encountered: