@bsweger described the initial problem and @zkamvar helped troubleshoot:
We're setting up a hub that asks modelers to predict a different set of COVID variants for each round. So each week, our plan is to update tasks.json with a new round object in rounds. Creating a brand new task config works well, but I'm struggling to update an existing task config with a new round because read_config() returns a list and write_config() wants an object of class <config>
I used create_rounds to successfully create a new round for the hub but where I ran into trouble was manipulating the existing config file (so we can add the new round and write it back out OR write a new config file that contains all prior rounds + new round)
task_config <- hubUtils::read_config(".", config = c("tasks"))
existing_round <- task_config$rounds[[1]]
# read_config returns a list, not a config object, so you can't parse the
# rounds into round objects
class(existing_round)
[1] "list"
# thus, create_rounds fails
create_rounds(existing_round)
Error in create_rounds(existing_round) :
! All items supplied must inherit from class <round>
✖ Item 1 does not.
Indeed this seems like far more effort than it should have been. In truth we had only developed as far as creating a fresh config. There are reasons it has ended up less straight forward with current functionality and that's because:
when we build config's out of components, some validation happens as components are created, some of which is facilitated by the schema.
Because of this we need to ensure all components are all being build against the same schema. As the config is constructed, this is checked.
Because it was getting really busy when retaining the schema_id and the class of each sub-component, I have actually been aggregating the schema_id as a top level attribute every time a higher level component is created and assigning an overarching class and dropping the sub-component classes (happy to revisit this if it might be useful, perhaps not for all sub-components but maybe for rounds?).
All this to say that's why it's a bit trickier interacting with sub-components once higher level components are built.
Proposed functionality
Initially, create:
[ ] an append_round() method which takes a round class object and appends it to to the rounds component of a config class object. This can also check that the new round was created against the same schema as the original config was.
[ ] an as_config() method to convert the output of read_config() to a <config> class object
In time we might decide that we always want to read in config files as <config> class objects, but that requires work in hubUtils also so let's leave that as a separate task.
Background
@bsweger described the initial problem and @zkamvar helped troubleshoot:
We're setting up a hub that asks modelers to predict a different set of COVID variants for each round. So each week, our plan is to update tasks.json with a new round object in rounds. Creating a brand new task config works well, but I'm struggling to update an existing task config with a new round because
read_config()
returns a list andwrite_config()
wants an object of class<config>
I used
create_rounds
to successfully create a new round for the hub but where I ran into trouble was manipulating the existing config file (so we can add the new round and write it back out OR write a new config file that contains all prior rounds + new round)What worked with current functionality:
Reasons behind difficulty
Indeed this seems like far more effort than it should have been. In truth we had only developed as far as creating a fresh config. There are reasons it has ended up less straight forward with current functionality and that's because:
schema_id
and the class of each sub-component, I have actually been aggregating theschema_id
as a top level attribute every time a higher level component is created and assigning an overarching class and dropping the sub-component classes (happy to revisit this if it might be useful, perhaps not for all sub-components but maybe for rounds?). All this to say that's why it's a bit trickier interacting with sub-components once higher level components are built.Proposed functionality
Initially, create:
append_round()
method which takes around
class object and appends it to to the rounds component of aconfig
class object. This can also check that the new round was created against the same schema as the original config was.as_config()
method to convert the output ofread_config()
to a<config>
class objectIn time we might decide that we always want to read in config files as
<config>
class objects, but that requires work inhubUtils
also so let's leave that as a separate task.