I have a Shiny app that is supposed to collect data in a form and appends it to a data table, test, in MySQL. I am using RMySQL to port into the database. The app should also show the dataframe. I use 'save' and 'load' functions to accomplish this, and I think the connection is valid, but for some reason the table 'object' is not found when the app is deployed.
Here is the error:
Error in sprintf("SELECT * FROM %s", test) : object 'test' not found
When I remove the load and/or the save functions, the error goes away.
Here is part of my global.R file. The queries are functions that are run after user-inputs define the type of data to be obtained. In this app, the type of data are data in a MySQL database.
# decide which function to use to save based on storage type
get_save_fxn <- function(type) {
fxn <- sprintf("save_data_%s", type)
fxn
}
save_data <- function(data, type) {
fxn <- get_save_fxn(type)
do.call(fxn, list(data))
}
# decide which function to use to load based on storage type
get_load_fxn <- function(type) {
fxn <- sprintf("load_data_%s", type)
fxn
}
load_data <- function(type) {
fxn <- get_load_fxn(type)
data <- do.call(fxn, list())
# Just for a nicer UI, if there is no data, construct an empty
# dataframe so that the colnames will still be shown
if (nrow(data) == 0) {
data <-
matrix(nrow = 0, ncol = length(fields_all),
dimnames = list(list(), fields_all)) %>%
data.frame
}
data %>% dplyr::arrange(desc(timestamp))
}
load_data_mysql <- function() {
on.exit(dbDisconnect(db))
db <- dbConnect(RMySQL::MySQL(),user="name",
password="pass",
host="host",
dbname="bk")
query <- sprintf("SELECT * FROM %s", test)
data <- dbGetQuery(db, query)
}
save_data_mysql <- function(data) {
on.exit(dbDisconnect(db))
db <- dbConnect(RMySQL::MySQL(),user="name",
password="pass",
host="host",
dbname="bk")
query <-
sprintf("INSERT INTO %s (%s) VALUES ('%s')",
test,
paste(names(data), collapse = ", "),
paste(data, collapse = "', '")
)
dbGetQuery(db, query)
}
Here is my server.R
# Enable the Submit button when all mandatory fields are filled out
observe({
fields_filled <-
fields_mandatory %>%
sapply(function(x) !is.null(input[[x]]) && input[[x]] != "") %>%
all
shinyjs::toggleState("submit", fields_filled)
})
# Gather all the form inputs
form_data <- reactive({
sapply(fields_all, function(x) x = input[[x]])
})
# When the Submit button is clicked
observeEvent(input$submit, {
# Update the timestamp field to be the current time
updateTextInput(session, "timestamp", value = get_time_epoch())
# User-experience stuff
shinyjs::disable("submit")
shinyjs::show("submitMsg")
shinyjs::hide("error")
on.exit({
shinyjs::enable("submit")
shinyjs::hide("submitMsg")
})
# Save the data (show an error message in case of error)
tryCatch({
save_data(form_data(), input$storage)
shinyjs::reset("form")
updateTabsetPanel(session, "mainTabs", "viewTab")
},
error = function(err) {
shinyjs::text("errorMsg", err$message)
shinyjs::show(id = "error", anim = TRUE, animType = "fade")
shinyjs::logjs(err)
})
})
# Update the responses whenever a new submission is made or the
# storage type is changed
responses_data <- reactive({
input$submit
load_data(input$storage)
})
# Show the responses in a table
output$responsesTable <- DT::renderDataTable(
DT::datatable(
responses_data(),
rownames = FALSE,
options = list(searching = FALSE, lengthChange = FALSE, scrollX = TRUE)
)
)
# Allow user to download responses
output$downloadBtn <- downloadHandler(
filename = function() {
paste0(TEST_INPUT, "_", input$storage, "_", get_time_human(), '.csv')
},
content = function(file) {
write.csv(responses_data(), file, row.names = FALSE)
}
)