-
-
Notifications
You must be signed in to change notification settings - Fork 6
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Change dispatch method to S3 instead of custom (target: @132_filter_panel_ui@main
)
#501
Change dispatch method to S3 instead of custom (target: @132_filter_panel_ui@main
)
#501
Conversation
@132_filter_panel_ui@main
)
I can't override options(teal.log_level = "TRACE", teal.show_js_log = TRUE, teal.bs_theme = bslib::bs_theme(version = 3))
library(shiny)
library(teal)
pkgload::load_all("teal.data")
library(teal.modules.hermes)
tdata <- teal_data() |>
within({
set.seed(1)
library(scda)
library(airway)
library(MultiAssayExperiment)
library(stats)
ts_example <- ts(matrix(rnorm(300), 100, 3), start = c(1961, 1), frequency = 12)
data(miniACC, envir = environment())
data(airway, envir = environment())
a_matrix <- matrix(rnorm(100), ncol = 5, dimnames = list(rownames = NULL, colnames = c("a", "b", "c", "d", "e")))
a_vector <- "elo"
ADSL <- synthetic_cdisc_data("latest")$adsl
ADSL$categorical <- sample(letters[1:3], size = nrow(ADSL), replace = TRUE, prob = c(.1, .3, .6))
ADTTE <- synthetic_cdisc_data("latest")$adtte
ADRS <- synthetic_cdisc_data("latest")$adrs
})
datanames(tdata) <- c("ADSL", "ADTTE", "ADRS", "miniACC", "airway", "a_vector", "a_matrix", "ts_example")
join_keys(tdata) <- default_cdisc_join_keys[c("ADSL", "ADTTE", "ADRS")]
default_filters <- teal.slice::teal_slices(
teal_slice(dataname = "ADSL", varname = "categorical", selected = c("a"), id = "categorical", multiple = FALSE),
count_type = "all"
)
get_filter_call.data.frame <- function(data, states_list) {
cat("THIS IS A LOG--------------------------------------------------------------/n")
dataname_lang <- str2lang(states_list[[1L]]$get_state()$dataname)
states_predicate <- lapply(states_list, function(state) state$get_call())
combined_predicate <- calls_combine_by(states_predicate, "&")
rhs <- as.call(c(str2lang("subset"), c(list(dataname_lang), combined_predicate)))
substitute(
expr = dataname_lang <- rhs,
env = list(dataname_lang = dataname_lang, rhs = rhs)
)
}
registerS3method("get_filter_call", "data.frame", teal.slice::get_filter_call)
app <- init(
data = tdata,
modules = modules(
modules(
label = "tab1",
example_module("funny"),
example_module("funny", datanames = "airway"),
example_module("funny2", datanames = "ADTTE"), # will limit datanames to ADTTE and ADSL (parent),
teal.modules.general::tm_data_table()
)
),
filter = default_filters
)
runApp(app)
|
The method is defined in the global environment, correct? |
Yes. Should it make any difference? Normally when there is some S3 generic, for example in within.data.frame <- function(data, expr, ...) {
stop("hihi")
}
within(iris)
obj <- structure(list(), class = "very_custom")
within.very_custom <- function(data, expr, ...) {
stop("very hihi")
}
within.very_custom(obj)
One doesn't need to do any fancy stuff to register new S3 method or to overwrite one. @averissimo please provide reproducible example to prove that overriding existing method is possible both in the |
Just checking. In my experience this should work, in fact I have used this mechanism myself a number of times. What happens if you add |
|
Sorry. I mean if the definition were in the package. But that's not the point, is it? |
You're right, it seems like the dispatch method will not work as intended and overwrite the methods *within* {teal.slice} (only outside this namespace) We would need to (forcibly) change the namespace in {teal.slice} with
You're initial solution achieves this customization via a manual dispatch that can be overwritten with S3methods. I think we can close this PR Some extra research trying to work aroud it:Trying to find workarounds I particularly enjoyed reading the documentation Anyway, we can change the library(teal.slice)
#> Loading required package: shiny
new_dispatch <- function(data, states_list) {
cat("THIS IS A LOG --------------------------------------------------------------/n")
# ...
}
registerS3method("get_filter_call", "data.frame", new_dispatch, envir = environment(get_filter_call))
environment(get_filter_call)[[".__S3MethodsTable__."]]$get_filter_call.data.frame
#> function(data, states_list) {
#> cat("THIS IS A LOG --------------------------------------------------------------/n")
#> # ...
#> }
getS3method("get_filter_call", "data.frame", envir = environment(get_filter_call))
#> function(data, states_list) {
#> cat("Original method --------------------------------------------------------------", "\n")
#> browser()
#> browser()
#> dataname_lang <- str2lang(states_list[[1L]]$get_state()$dataname)
#> states_predicate <- lapply(states_list, function(state) state$get_call())
#> combined_predicate <- calls_combine_by(states_predicate, "&")
#> rhs <- as.call(c(str2lang("dplyr::filter"), c(list(dataname_lang), combined_predicate)))
#>
#> substitute(
#> expr = dataname_lang <- rhs,
#> env = list(dataname_lang = dataname_lang, rhs = rhs)
#> )
#> }
#> <environment: namespace:teal.slice> |
Additional note: the search of S3methods have been changing since 3.4, so an overwritten method may have been possible in the past |
Update: methods can be overwritten in S4. I redefined
both in the global environment and in a package that Depends on In both cases I received
So we can get rid of the non-standard dispatch on |
Tested with:
get_filter_call
method with a blank package called {overwrite} (see below)@importFrom
roxygen2 tag is fundamentalnote: My concern with the order of library / pkgload::load_all doesn't matter as {overwrite} imports from {teal.slice} and will re-register the method
{overwrite} package
Example of the {overwrite} in place
Note that this is non-reproducible as the {overwrite} package needs to be installed
Teal app
Tested with branch of {teal}
132_filter_panel_ui@main
.