Skip to content

Commit

Permalink
Merge pull request #494 from OuhscBbmc/dev
Browse files Browse the repository at this point in the history
`validate_for_write()` subfunctions
  • Loading branch information
wibeasley authored Jul 11, 2023
2 parents 301f31e + ab4c58a commit 0d69b0e
Show file tree
Hide file tree
Showing 26 changed files with 532 additions and 102 deletions.
1 change: 1 addition & 0 deletions NAMESPACE
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ export(validate_data_frame_inherits)
export(validate_field_names)
export(validate_for_write)
export(validate_no_logical)
export(validate_record_id_name)
export(validate_repeat_instance)
export(validate_uniqueness)
importFrom(magrittr,"%>%")
Expand Down
13 changes: 10 additions & 3 deletions NEWS.md
Original file line number Diff line number Diff line change
Expand Up @@ -74,14 +74,21 @@ This will help extract forms from longitudinal & repeating projects.
* `redcap_file_upload_oneshot()` to `redcap_file_upload_opneshot()`
* `redcap_download_instrument()` to `redcap_instrument_download()`
* `redcap_dag_read()` has new `data_access_group_id` field (introduced maybe in [13.1.0](https://community.projectredcap.org/articles/13/index.html)) (#459)
* `redcap_users_export()` has new `mycap_participants` field (introduced maybe in [13.0.0](https://community.projectredcap.org/articles/13/index.html)) (#459)
* `redcap_dag_read()` has new `data_access_group_id` field (introduced maybe in [13.1.0](https://redcap.vanderbilt.edu/community/post.php?id=13)) (#459)
* `redcap_users_export()` has new `mycap_participants` field (introduced maybe in [13.0.0](https://redcap.vanderbilt.edu/community/post.php?id=13)) (#459)
* Accommodate older versions of REDCap that don't return project-level variable, like `has_repeating_instruments_or_events`, `missing_data_codes`, `external_modules`, `bypass_branching_erase_field_prompt` (@the-mad-statter, #465, #466)
* `redcap_meta_coltypes()` correctly determines data type for autonumber `record_id` fields. It suggests a character if the project has DAGs, and an integer if not. (@pwildenhain, #472)
* `redcap_log_read()` now returns a new column reflecting the affected record id value (ref #478)
* `redcap_read()` and `redcap_read_oneshot()` now remove "pseudofields" (e.g., `redcap_event_name`, `redcap_repeat_instrument`, & `redcap_repeat_instance`) from the `fields` parameter. Starting with REDCap v13.4.10, an error is thrown by the server. REDCap will return a message if a common pseudofield is requested explicitly by the user. (#477)
* `redcap_event_instruments()` now can return mappings for all arms, instead of one arm per call.(Suggested by @januz, #482)
* `validate_for_write()` contains a few more checks, such as `validate_repeat_instance()` and `validate_data_frame_inherits()` (#485)
* `validate_for_write()` contains a few more checks. (#485) The complete list is now:
* `validate_data_frame_inherits()`
* `validate_field_names()`
* `validate_record_id_name()`
* `validate_uniqueness()`
* `validate_repeat_instance()`
* `validate_no_logical()`
* `redcap_read()` checks the `event` parameter and throws an error if a value is not recognized, or the project is not longitudinal (#493)

Version 1.1.0 (released 2022-08-10)
==========================================================
Expand Down
2 changes: 1 addition & 1 deletion R/redcap-file-download-oneshot.R
Original file line number Diff line number Diff line change
Expand Up @@ -142,7 +142,7 @@ redcap_file_download_oneshot <- function(
record <- as.character(record)
checkmate::assert_character(record , any.missing=FALSE, len=1, pattern="^.{1,}$")
checkmate::assert_character(field , any.missing=FALSE, len=1, pattern="^.{1,}$")
validate_field_names(field, stop_on_error = TRUE)
assert_field_names(field)
checkmate::assert_character(event , any.missing=FALSE, len=1, pattern="^.{0,}$")
checkmate::assert_logical( verbose , any.missing=FALSE)

Expand Down
2 changes: 1 addition & 1 deletion R/redcap-file-upload-oneshot.R
Original file line number Diff line number Diff line change
Expand Up @@ -124,7 +124,7 @@ redcap_file_upload_oneshot <- function(
checkmate::assert_character(redcap_uri , any.missing=FALSE, len=1, pattern="^.{1,}$")
checkmate::assert_character(token , any.missing=FALSE, len=1, pattern="^.{1,}$")
checkmate::assert_character(field , any.missing=FALSE, len=1, pattern="^.{1,}$")
validate_field_names(field, stop_on_error = TRUE)
assert_field_names(field)
checkmate::assert_character(event , any.missing=FALSE, len=1, pattern="^.{0,}$")
checkmate::assert_logical( verbose , any.missing=FALSE)

Expand Down
2 changes: 1 addition & 1 deletion R/redcap-metadata-read.R
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@ redcap_metadata_read <- function(
checkmate::assert_character(redcap_uri , any.missing=FALSE, len=1, pattern="^.{1,}$")
checkmate::assert_character(token , any.missing=FALSE, len=1, pattern="^.{1,}$")

validate_field_names(fields, stop_on_error = TRUE)
assert_field_names(fields)

token <- sanitize_token(token)
fields_collapsed <- collapse_vector(fields)
Expand Down
2 changes: 1 addition & 1 deletion R/redcap-read-eav-oneshot.R
Original file line number Diff line number Diff line change
Expand Up @@ -227,7 +227,7 @@ redcap_read_eav_oneshot <- function(
checkmate::assert_list( config_options , any.missing=TRUE , null.ok=TRUE)
# checkmate::assert_character(encode_httr , any.missing=FALSE, len=1, null.ok = FALSE)

validate_field_names(fields, stop_on_error = TRUE)
assert_field_names(fields)

token <- sanitize_token(token)
records_collapsed <- collapse_vector(records)
Expand Down
2 changes: 1 addition & 1 deletion R/redcap-read-oneshot-eav.R
Original file line number Diff line number Diff line change
Expand Up @@ -195,7 +195,7 @@ redcap_read_oneshot_eav <- function(
checkmate::assert_logical( verbose , any.missing=FALSE, len=1, null.ok=TRUE)
checkmate::assert_list( config_options , any.missing=TRUE , null.ok=TRUE)

validate_field_names(fields, stop_on_error = TRUE)
assert_field_names(fields)

token <- sanitize_token(token)
records_collapsed <- collapse_vector(records)
Expand Down
2 changes: 1 addition & 1 deletion R/redcap-read-oneshot.R
Original file line number Diff line number Diff line change
Expand Up @@ -253,7 +253,7 @@ redcap_read_oneshot <- function(
checkmate::assert_list( config_options , any.missing=TRUE , null.ok=TRUE)
# checkmate::assert_character(encode_httr , any.missing=FALSE, len=1, null.ok = FALSE)

validate_field_names(fields, stop_on_error = TRUE)
assert_field_names(fields)

pseudofields <- c(
"redcap_event_name",
Expand Down
53 changes: 49 additions & 4 deletions R/redcap-read.R
Original file line number Diff line number Diff line change
Expand Up @@ -118,7 +118,8 @@
#' a zero-row tibble is returned.
#' Currently the empty tibble has zero columns, but that may change in the future.
#'
#' @details
#' @section Batching subsets of data:
#'
#' [redcap_read()] internally uses multiple calls to [redcap_read_oneshot()]
#' to select and return data. Initially, only the primary key is queried
#' through the REDCap API. The long list is then subsetted into batches,
Expand Down Expand Up @@ -148,6 +149,8 @@
#' 1. `redcap_repeat_instrument` and `redcap_repeat_instance` will be returned
#' for projects with repeating instruments
#'
#' @section Export permissions:
#'
#' For [redcap_read_oneshot()] to function properly, the user must have Export
#' permissions for the 'Full Data Set'. Users with only 'De-Identified'
#' export privileges can still use `redcap_read_oneshot`. To grant the
Expand All @@ -156,6 +159,8 @@
#' * select the desired user, and then select 'Edit User Privileges',
#' * in the 'Data Exports' radio buttons, select 'Full Data Set'.
#'
#' @section Pseudofields:
#'
#' The REDCap project may contain "pseudofields", depending on its structure.
#' Pseudofields are exported for certain project structures, but are not
#' defined by users and do not appear in the codebook.
Expand All @@ -182,6 +187,22 @@
#' ERROR: The following values in the parameter fields are not valid: 'demographics_timestamp'
#' ```
#'
#' @section Events:
#' The `event` argument is a vector of characters passed to the server.
#' It is the "event-name", not the "event-label".
#' The event-label is the value presented to the users,
#' which contains uppercase letters and spaces,
#' while the event-name can contain only lowercase letters, digits,
#' and underscores.
#'
#' If `event` is nonnull and the project is not longitudinal,
#' [redcap_read()] will throw an error.
#' Similarly, if a value in the `event` vector is not a current
#' event-name, [redcap_read()] will throw an error.
#'
#' The simpler [redcap_read_oneshot()] function does not
#' check for invalid event values, and will not throw errors.
#'
#' @author
#' Will Beasley
#'
Expand Down Expand Up @@ -283,7 +304,7 @@ redcap_read <- function(
checkmate::assert_list( config_options , any.missing=TRUE , null.ok=TRUE)
checkmate::assert_integer( id_position , any.missing=FALSE, len=1, lower=1L)

validate_field_names(fields, stop_on_error = TRUE)
assert_field_names(fields)

token <- sanitize_token(token)
filter_logic <- filter_logic_prepare(filter_logic)
Expand All @@ -300,10 +321,33 @@ redcap_read <- function(
handle_httr = handle_httr
)

# browser()
if (!is.null(fields) || !is.null(forms))
if (!is.null(events)) {
if (!metadata$longitudinal) {
"This project is NOT longitudinal, so do not pass a value to the `event` argument." %>%
stop(call. = FALSE)
} else {
events_in_project <-
redcap_event_read(
redcap_uri,
token,
verbose = verbose,
config_options = config_options,
handle_httr = handle_httr
)$data[["unique_event_name"]]

events_not_recognized <- setdiff(events, events_in_project)
if (0L < length(events_not_recognized)) {
"The following events are not recognized for this project: {%s}.\nMake sure you're using internal `event-name` (lowercase letters & underscores)\ninstead of the user-facing `event-label` (that can have spaces and uppercase letters)." %>%
sprintf(paste(events_not_recognized, collapse = ", ")) %>%
stop(call. = FALSE)
}
} # end of else
} # end of !is.null(events)

if (!is.null(fields) || !is.null(forms)) {
fields <- base::union(metadata$record_id_name, fields)
# fields <- base::union(metadata$plumbing_variables, fields)
}

# Retrieve list of record ids --------------------------------------
initial_call <- REDCapR::redcap_read_oneshot(
Expand Down Expand Up @@ -405,6 +449,7 @@ redcap_read <- function(
" (ie, ", length(selected_ids), " unique subject records)."
)
}

read_result <- REDCapR::redcap_read_oneshot(
redcap_uri = redcap_uri,
token = token,
Expand Down
Loading

0 comments on commit 0d69b0e

Please sign in to comment.