config
config copied to clipboard
Allow for a "config.user.yml" by default
In many projects, there are "default" and "available" values that are stored in config.yml. However, sometimes a fork / implementation of the project may want to use different parameters without
It'd be really nice to allow a default like config.user.yml that could be .gitignore'd for user modifications without retaining dirty git state, templatizing config.yml, etc.
config::get("myvalue")
Would:
- read values from
config.ymlas per usual - overwrite values from
config.ymlwith those fromconfig.user.yml - potentially allow unsetting values in
config.user.ymlsomehow? By setting tonull?
This would also be useful in local development where I would for example want to connect to my local database instead of a production one.
The same can roughly be achieved using the environments, but I feel the file overload is pragmatically simpler and faster.
I think it can be managed with the available package functions in few lines of code.
Let's say that we have a global configuration file that is versionned on the repository:
lGlobalConf <- list(default = list(trials = 5, dataset = "data-complete.csv", extra = "Something",
subParam = list(a = 1, b = 2)))
yaml::write_yaml(lGlobalConf, file = "config.yml")
which is the following yaml file:
default:
trials: 5.0
dataset: data-complete.csv
extra: Something
subParam:
a: 1.0
b: 2.0
And a use config file that overwrite some global options on a config file not versionned on the repository:
lUserConf <- list(default = list(dataset = "data-sampled.csv", extra = NULL, subParam = list(b = 99)))
yaml::write_yaml(lUserConf, file = "config.user.yml")
which is the following yaml file:
default:
dataset: data-sampled.csv
extra: ~
subParam:
b: 99.0
We can manage the overwrite mechanism this way with the current functions in the 'config' package:
rm(list = ls()) # Reset R session memory
# Load global configuration
cfg <- config::get()
# Load user configuration if exists
if(file.exists("config.user.yml")) cfgUser <- config::get(file = "config.user.yml")
# Merge configuration with user values overwritting global values
cfg <- config::merge(cfg, cfgUser)
#Display resulting configuration
str(cfg)
List of 4
$ subParam:List of 2
..$ a: num 1
..$ b: num 99
$ trials : num 5
$ dataset : chr "data-sampled.csv"
$ extra : NULL
We can see that user parameters have overwritten global ones even in nested structures. The NULL value doesn't remove the related configuration key as expected but since a condition is.null(cfg.extra) returns the same value whether the list item exists or not, I don't think this is a real issue.
What do you think about it?
I want to deploy my application on the rsconnect server, but I can't connect to the data in the rsconnect vault. I have created a config.yml file as follows:
default:
data_CI: 'Y:/Production/Flavour Common/MACDATA/DATAHOUSE/Rshiny/'
rsconnect:
data_CI: '/userdata/macdata/data/'
I don't use a driver to connect the data. I have access to the files in the rsconnect thanks to WinCSP which allows me to add the files and to give them the rights of reading or writing When I test my application locally, it works fine, but when I go into the server, I get an error message like this:
Warning: Error in : `.x` is empty, and no `.init` supplied
06/09 07:31:11.345 (GMT)
[No stack trace available]
Please help me ! Thank in advance
@yannessanga, I don't think your question is related to the topic of this issue which is relative to a particular feature request on config. I don't even know if your problem is related to the use of the config package or rsconnect. You should probably ask your question on https://stackoverflow.com/ to get help from users.
I have implement to concept "default" and "user" config with a default configuration provided by a package and a user one provided by a 'config.yml' file located by default in the working directory. In that way the user of the package can overwrite some pieces of the configuration:
#' Read default configuration of the package and complete it with eventual user config
#'
#' @param userFile location of the user config YML file
#' @param package The package where stand the default configuration (located in "inst/config.yml" of the package by default)
#'
#' @return A configuration as it is returned by [config::get]
#' @export
#'
#' @examples
#' cfg <- getConfig()
#' str(cfg)
getConfig <- function(userFile = "config.yml", pathDefaultCfg = system.file("config.yml", package = "myPackage")) {
cfg <- config::get(file = pathDefaultCfg)
if(file.exists(userFile)) {cfg = config::merge(cfg,config::get(file = userFile))}
cfg
}
I think it's not necessary to implement mechanism of default/user config in the config package. Because (1) there is no obvious way to implement this (config.yml/config.user.yml vs different paths) and (2) it is relatively easy to write your own script of such a mechanism in 3 lines of code.
So, I am in favour of closing this feature request.