I'm trying to create an MVC (Angular) site development library in R using the plumber route system, but I'm stagnant on a part of the system that I still can not solve.
Using the Plumber class, I created a method in my R6 class to generate the routes, where I pass parameters to it but when I run the plumber it generates error in creating the route because it can not identify the callback (function (req, res)) of the handle function .
make_route = function (route_method, route_name, route_path, is_html) {
private$plumber$handle(route_method, route_path, function (req, res) {
view_name <- tolower(gsub(".", "/", gsub("_", "/", route_name, fixed = T), fixed = T))
route_name <- gsub(" ", "", str_to_title(gsub(".", " ", gsub("_", " ", route_name, fixed = T), fixed = T)), fixed = T)
controller_name <- paste0(route_name, "Controller")
model_name <- route_name
model <- NULL
if (model_name %in% ls()) {
model <- eval(parse(
text = paste0(model_name, "$new()")
))
}
model <- NULL
controller <- eval(parse(
text = paste0(controller_name, "$new(model, req, res)")
))
response <- controller$boot()
if (is_html) {
res$setHeader("Content-Type", "text/html; charset=utf-8")
if (file.exists(paste0("./resources/view/", view_name, ".html"))) {
view <- read_file(paste0("./resources/view/", view_name, ".html"))
}
html <- self$processor$process(view, response)
return (self$processor$output(read_file("./public/index.html"), html))
} else {
res$setHeader("Content-Type", "application/json; charset=utf-8")
return (response)
}
})
}
(full code in: Github)
I still don't know how to create this function and generate all the routes in a friendly and dynamic way (I also think of storing the routes in a JSON to facilitate the development and performance of the application as a whole).
Does anyone have any light? Or should I give up?
I believe the approach is fine. (Function encapsulate when adding a new handle)
Can you provide me with the whole traceback() of the error?
@schloerke Hi!
I tried again, but still the same.
traceback:
14: execCallbacks(timeoutSecs, all, loop$id)
13: run_now(check_time, all = FALSE)
12: service(0)
11: httpuv::runServer(host, port, self)
10: private$plumber$run(api_host, api_port) at Router.R#35
9: Router$run(App$environments$APP_HOST, App$environments$APP_PORT) at bootstrap.R#4
8: eval(ei, envir)
7: eval(ei, envir)
6: withVisible(eval(ei, envir))
5: source("resources/bootstrap.R") at lambR.R#6
4: eval(ei, envir)
3: eval(ei, envir)
2: withVisible(eval(ei, envir))
1: source("./lambR.R")
@aleDsz I've downloaded your repo and I'm able to run it. Don't know how to help much.
lambR-master: R
> install.packages("plumber")
trying URL 'https://cloud.r-project.org/bin/macosx/contrib/4.0/plumber_0.4.6.tgz'
(Content type 'application/x-gzip' length 357004 bytes (348 KB)
==================================================
downloaded 348 KB
The downloaded binary packages are in
/var/folders/0k/bxg5lhr92sq74mb1d446ql540000gp/T//RtmpZTn9T1/downloaded_packages
> source("lambR.R")
Attaching package: ‘dplyr’
The following objects are masked from ‘package:plyr’:
arrange, count, desc, failwith, id, mutate, rename, summarise, summarize
The following objects are masked from ‘package:stats’:
filter, lag
The following objects are masked from ‘package:base’:
intersect, setdiff, setequal, union
Starting server to listen on port 8080
Running the swagger UI at http://127.0.0.1:8080/__swagger__/
@schloerke But if u try to access http://127.0.0.1:8080 you will see the error he throws because he doesn't recognize how to process the line:
private$plumber$handle(route_method, route_path, function (req, res) {
# [...]
Your problem is that self$processor$process(view, response) does not exist. Nothing to do with plumber.
Browse[1]>
debug at ./app/Router.R#75: html <- self$processor$process(view, response)
Browse[2]> self$processor
NULL
Browse[2]> self$processor$process(view, response)
Error: attempt to apply non-function
It's processing it. The function has multiple errors.
self$processor defined. initialize = function (plumber, App) {
self$processor <- WebProcessor$new()
res in your route to not have the HTML be sent through the default JSON parser. Also change processor$process to processor$process_html html <- self$processor$process_html(view, response)
res$body <- self$processor$output(read_file("./public/index.html"), html)
return (res)
view folder, change folder /view/ to /views/ to match repo structure if (file.exists(paste0("./resources/views/", view_name, ".html"))) {
view <- read_file(paste0("./resources/views/", view_name, ".html"))
}
WebProcessor response argument is missing an s process_html = function (html, response) {
Final product:

Hope this helps!
(Closing as issue is not plumber related)
If you have to troubleshoot R code, check out browser() and debugonce(). They are really useful and you can find out what is going on within your code and other libraries code. Hopefully, things will go smoothly from here.