Preparation and course runner
Prepare once, then continue in the same R session.
Download the R script ↓The download places H01 to H04 before the course runner. If copying from this website, run only Preparation: load the package first, complete H01 to H04, then return here and run the course runner. This keeps your objects and log consistent with the script.
How to use this course
Each main-path step takes about 5-10 minutes. Longer modules are split into smaller substeps. Stop whenever you have learned enough for today. H01-H24 start locally; H25-H39 cover the lake and reporting; E modules are manual editor exercises; V modules are optional deep dives. Prerequisites appear before each block. Default: local exercises run if their packages are installed. Packages and database extensions are never installed automatically. DuckLake, GUI and external services are initially disabled. Set options BEFORE running the script, for example: options(dataraft.training = list(lake = TRUE, extras = TRUE)) options(dataraft.training = list(lake = TRUE, install_extensions = TRUE)) Available switches: lake, extras, gui, dbt, api, catalogs, postgres, s3, iceberg, install_extensions. Enable only prepared integrations. V25 offers a separate offline DuckDB alternative. Install optional components only when needed: adapters for persistence; metrics for metrics; lake for DuckLake; ide for the extension; dbt for dbt. Catalog integrations live in adapters. Exact source commits appear at the end. Install components analogously to the core setup, with Depends/Imports/LinkingTo only, in order: core, lake, metrics, dbt, adapters, ide. Use a coordinated version set. For durable course output, set options(dataraft.training_root = "~/dataraft-training"). Each full run gets a new subdirectory. Without this option, files go into tempdir() and may disappear after the session. Use training resources only; do not put credentials in this script. Try each task before reading its solution. Keep experiments in new objects. training_step is a COURSE HELPER, not a DataRaft API. It skips disabled or missing prerequisites, retains objects in the course workspace and records results. Local errors stop; optional errors are recorded and dependent exercises are skipped.
DataRaft step by step
Complete course: H01-H39, E01-E15, V01-V25. Source and test snapshot: September 23, 2026. English website edition. Open this file in Positron and execute sections from top to bottom. Read the explanation, run the small block, inspect the result and try the task. Section marks support navigation in the editor outline. You need basic R knowledge: assignment, function calls and tables. No lake or extension is needed at the beginning. H01-H11 create R objects only. Data is synthetic and reproducible. A complete rerun resets the named course objects; use a separate R session. Underlying code validation: H01-H24, H34 and H38 executed in a fresh R session. H25-H39 also executed with DuckDB 1.5.5 and DuckLake. Report integrity, environment and replay checks returned match. Local deep dives executed with pointblank, Excel, SQLite, Parquet, pins and targets; the dbt starter including contract and publication was executed. The API adapter was checked against a local HTTP fixture. E-module R preparation was executed, but no actual Positron click tests were performed for this course. Not tested end to end: PostgreSQL, S3, OpenLineage, OpenMetadata, Iceberg, the two-process writing experiment and a custom dbt transformation project. Original test environment: R 4.5.3, dm 1.1.2.9017, dplyr 1.2.1, dbt-core 1.12.5, dbt-duckdb 1.11.0. The current course uses DataRaft 0.1.0.9006; exact SHAs appear below. An earlier base test also used R 4.4.3. Translation preserves the executable exercises apart from English display labels and messages. The current API cleanup was rechecked locally with R 4.3.3: H01-H38 passed, including DuckLake. H39 requires Shiny/bslib; editor and external-service exercises remain explicitly opt-in. CI separately exercises the package and editor integration suites. Follow data, product definition, run result and explicit contract first. Then add quality, recipes, persistence, customers and brokers, metrics, DuckLake, the extension and optional integrations.
00 Optional setup: only for missing packages
# These installation commands are deliberately commented out. Run them separately only when
# needed, then restart R. They require internet access; some dependencies need binaries or build
# tools.
# install.packages("remotes", repos = "https://cloud.r-project.org")
# remotes::install_github(
# "dataraft-r/dataraft.core@69d0212bdd6b1e1e8a93fd948d3616f9cdad5092",
# dependencies = c("Depends", "Imports", "LinkingTo"),
# upgrade = "never", build_vignettes = FALSE
# )
# Only core and its required dependencies are needed initially. Optional family packages and
# their Remotes are not requested here. This commented remotes installation path was not
# executed during validation; pinned sources were installed locally for the tests.00 Preparation: load the package
Check the R and package versions before starting. The pinned core version is 0.1.0.9005. Newer versions may differ, so keep the result checks.
if (getRversion() < "4.2.0") {
stop("This course requires R >= 4.2.0.", call. = FALSE)
}
if (!requireNamespace("dataraft.core", quietly = TRUE)) {
stop("dataraft.core is missing. Run the optional setup first.", call. = FALSE)
}
if (utils::packageVersion("dataraft.core") < "0.1.0.9005") {
stop("Please update dataraft.core to at least 0.1.0.9005.", call. = FALSE)
}
library(dataraft.core)
utils::packageVersion("dataraft.core")Course runner for the following modules
Run this after H04. It creates a fresh course directory, applies your opt-in switches and defines training_step. The helper checks prerequisites before evaluating code in the current course workspace. A skipped step is not a successful test.
training_options <- utils::modifyList(
list(
lake = FALSE,
extras = FALSE,
gui = FALSE,
dbt = FALSE,
api = FALSE,
catalogs = FALSE,
postgres = FALSE,
s3 = FALSE,
iceberg = FALSE,
install_extensions = FALSE
),
getOption("dataraft.training", list())
)
training_parent <- path.expand(getOption("dataraft.training_root", tempdir()))
dir.create(training_parent, recursive = TRUE, showWarnings = FALSE)
training_root <- tempfile("dataraft-course-", tmpdir = training_parent)
dir.create(training_root, recursive = TRUE)
message("Your course directory: ", training_root)
training_log <- new.env(parent = emptyenv())
for (id in sprintf("H%02d", 1:4)) {
training_log[[id]] <- "ok"
}
training_step <- function(
id,
code,
needs = character(),
packages = character(),
enabled = TRUE,
optional = FALSE
) {
reason <- if (!isTRUE(enabled)) "disabled" else NULL
if (is.null(reason) && length(needs)) {
missing <- needs[
!vapply(needs, function(x) identical(training_log[[x]], "ok"), logical(1))
]
if (length(missing)) {
reason <- paste("Missing prerequisite:", paste(missing, collapse = ", "))
}
}
if (is.null(reason) && length(packages)) {
missing <- packages[
!vapply(packages, requireNamespace, logical(1), quietly = TRUE)
]
if (length(missing)) {
reason <- paste("Missing package:", paste(missing, collapse = ", "))
}
}
if (!is.null(reason)) {
training_log[[id]] <- paste("skipped:", reason)
message(id, " | ", training_log[[id]])
return(invisible(NULL))
}
expr <- substitute(code)
scope <- parent.frame()
tryCatch(
{
eval(expr, envir = scope)
training_log[[id]] <- "ok"
message(id, " | completed")
},
error = function(e) {
training_log[[id]] <- paste("Error:", conditionMessage(e))
if (!optional) {
stop(id, ": ", conditionMessage(e), call. = FALSE)
}
message(id, " | ", training_log[[id]])
}
)
invisible(NULL)
}