Skip to content

Commit

Permalink
deploy: 7572f97
Browse files Browse the repository at this point in the history
  • Loading branch information
romaninsh committed Nov 21, 2024
1 parent 5949676 commit 8d50df9
Show file tree
Hide file tree
Showing 9 changed files with 574 additions and 500 deletions.
269 changes: 269 additions & 0 deletions 1-dataset.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,269 @@
<!DOCTYPE HTML>
<html lang="en" class="light sidebar-visible" dir="ltr">
<head>
<!-- Book generated using mdBook -->
<meta charset="UTF-8">
<title>Data Sets - DORM - The Dry ORM</title>


<!-- Custom HTML head -->

<meta name="description" content="">
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta name="theme-color" content="#ffffff">

<link rel="icon" href="favicon.svg">
<link rel="shortcut icon" href="favicon.png">
<link rel="stylesheet" href="css/variables.css">
<link rel="stylesheet" href="css/general.css">
<link rel="stylesheet" href="css/chrome.css">
<link rel="stylesheet" href="css/print.css" media="print">

<!-- Fonts -->
<link rel="stylesheet" href="FontAwesome/css/font-awesome.css">
<link rel="stylesheet" href="fonts/fonts.css">

<!-- Highlight.js Stylesheets -->
<link rel="stylesheet" href="highlight.css">
<link rel="stylesheet" href="tomorrow-night.css">
<link rel="stylesheet" href="ayu-highlight.css">

<!-- Custom theme stylesheets -->


<!-- Provide site root to javascript -->
<script>
var path_to_root = "";
var default_theme = window.matchMedia("(prefers-color-scheme: dark)").matches ? "navy" : "light";
</script>
<!-- Start loading toc.js asap -->
<script src="toc.js"></script>
</head>
<body>
<div id="body-container">
<!-- Work around some values being stored in localStorage wrapped in quotes -->
<script>
try {
var theme = localStorage.getItem('mdbook-theme');
var sidebar = localStorage.getItem('mdbook-sidebar');

if (theme.startsWith('"') && theme.endsWith('"')) {
localStorage.setItem('mdbook-theme', theme.slice(1, theme.length - 1));
}

if (sidebar.startsWith('"') && sidebar.endsWith('"')) {
localStorage.setItem('mdbook-sidebar', sidebar.slice(1, sidebar.length - 1));
}
} catch (e) { }
</script>

<!-- Set the theme before any content is loaded, prevents flash -->
<script>
var theme;
try { theme = localStorage.getItem('mdbook-theme'); } catch(e) { }
if (theme === null || theme === undefined) { theme = default_theme; }
const html = document.documentElement;
html.classList.remove('light')
html.classList.add(theme);
html.classList.add("js");
</script>

<input type="checkbox" id="sidebar-toggle-anchor" class="hidden">

<!-- Hide / unhide sidebar before it is displayed -->
<script>
var sidebar = null;
var sidebar_toggle = document.getElementById("sidebar-toggle-anchor");
if (document.body.clientWidth >= 1080) {
try { sidebar = localStorage.getItem('mdbook-sidebar'); } catch(e) { }
sidebar = sidebar || 'visible';
} else {
sidebar = 'hidden';
}
sidebar_toggle.checked = sidebar === 'visible';
html.classList.remove('sidebar-visible');
html.classList.add("sidebar-" + sidebar);
</script>

<nav id="sidebar" class="sidebar" aria-label="Table of contents">
<!-- populated by js -->
<mdbook-sidebar-scrollbox class="sidebar-scrollbox"></mdbook-sidebar-scrollbox>
<noscript>
<iframe class="sidebar-iframe-outer" src="toc.html"></iframe>
</noscript>
<div id="sidebar-resize-handle" class="sidebar-resize-handle">
<div class="sidebar-resize-indicator"></div>
</div>
</nav>

<div id="page-wrapper" class="page-wrapper">

<div class="page">
<div id="menu-bar-hover-placeholder"></div>
<div id="menu-bar" class="menu-bar sticky">
<div class="left-buttons">
<label id="sidebar-toggle" class="icon-button" for="sidebar-toggle-anchor" title="Toggle Table of Contents" aria-label="Toggle Table of Contents" aria-controls="sidebar">
<i class="fa fa-bars"></i>
</label>
<button id="theme-toggle" class="icon-button" type="button" title="Change theme" aria-label="Change theme" aria-haspopup="true" aria-expanded="false" aria-controls="theme-list">
<i class="fa fa-paint-brush"></i>
</button>
<ul id="theme-list" class="theme-popup" aria-label="Themes" role="menu">
<li role="none"><button role="menuitem" class="theme" id="light">Light</button></li>
<li role="none"><button role="menuitem" class="theme" id="rust">Rust</button></li>
<li role="none"><button role="menuitem" class="theme" id="coal">Coal</button></li>
<li role="none"><button role="menuitem" class="theme" id="navy">Navy</button></li>
<li role="none"><button role="menuitem" class="theme" id="ayu">Ayu</button></li>
</ul>
<button id="search-toggle" class="icon-button" type="button" title="Search. (Shortkey: s)" aria-label="Toggle Searchbar" aria-expanded="false" aria-keyshortcuts="S" aria-controls="searchbar">
<i class="fa fa-search"></i>
</button>
</div>

<h1 class="menu-title">DORM - The Dry ORM</h1>

<div class="right-buttons">
<a href="print.html" title="Print this book" aria-label="Print this book">
<i id="print-button" class="fa fa-print"></i>
</a>

</div>
</div>

<div id="search-wrapper" class="hidden">
<form id="searchbar-outer" class="searchbar-outer">
<input type="search" id="searchbar" name="searchbar" placeholder="Search this book ..." aria-controls="searchresults-outer" aria-describedby="searchresults-header">
</form>
<div id="searchresults-outer" class="searchresults-outer hidden">
<div id="searchresults-header" class="searchresults-header"></div>
<ul id="searchresults">
</ul>
</div>
</div>

<!-- Apply ARIA attributes after the sidebar and the sidebar toggle button are added to the DOM -->
<script>
document.getElementById('sidebar-toggle').setAttribute('aria-expanded', sidebar === 'visible');
document.getElementById('sidebar').setAttribute('aria-hidden', sidebar !== 'visible');
Array.from(document.querySelectorAll('#sidebar a')).forEach(function(link) {
link.setAttribute('tabIndex', sidebar === 'visible' ? 0 : -1);
});
</script>

<div id="content" class="content">
<main>
<h1 id="data-sets"><a class="header" href="#data-sets">Data Sets</a></h1>
<p>Most of Rust apps operate with data which is readily available in memory. Business apps
are stateless, loading too much data is an anti-pattern.</p>
<p>Depending of the capabilities of the underlying data storage layer, you should look to
create as many requests and retrieve as little data as possible.</p>
<p><code>DataSet</code> is is a representation of collection of records - stored remotely.</p>
<h2 id="readabledataset-and-writabledataset"><a class="header" href="#readabledataset-and-writabledataset">ReadableDataSet and WritableDataSet</a></h2>
<p>DORM provides two traits: <code>ReadableDataSet</code> and <code>WritableDataSet</code>. DORM also provides
several implementations of these traits:</p>
<ul>
<li><code>sql::Table</code> - implements both <code>ReadableDataSet</code> and <code>WritableDataSet</code>.</li>
<li><code>sql::Query</code> - implements <code>ReadableDataSet</code> only.</li>
</ul>
<p>Design of DORM allow you to extend those into NoSQL (like MongoDB or GraphQL sources)
as well as custom RestAPI sources. Those extensions do not need to be part of DORM,
they can be implemented as separate crates.</p>
<h2 id="operating-with-data-sets"><a class="header" href="#operating-with-data-sets">Operating with Data sets</a></h2>
<p>At the very basic level - you can iterate through a readable data set.</p>
<pre><pre class="playground"><code class="language-rust"><span class="boring">#![allow(unused)]
</span><span class="boring">fn main() {
</span>let set_of_clients = Client::table();

for client in set_of_clients.get().await? {
println!("{}", client.name);
}
<span class="boring">}</span></code></pre></pre>
<p>But quite often the advanced persistence layer could allow us to do much more. DORM approach is
to provide ways how one Data Set can yield a different Data Set. Here are some examples:</p>
<ul>
<li>Get a set containing subset of records - by filtering.</li>
<li>Converting <code>sql::table</code> into <code>sql::query</code> for further manipulation.</li>
<li>Execute operation over set, such as calculate sum of a field from all records, or create comma-separated list of values.</li>
<li>Modify or delete multiple records.</li>
</ul>
<p>DORM prefers to off-load operation execution to the persistence layer, but because this may increase
complexity, DORM also provides a way to abstract this complexity away.</p>
<h3 id="example---lazy-expression-fields"><a class="header" href="#example---lazy-expression-fields">Example - Lazy expression fields</a></h3>
<p>In our introduction example, we came across an aggregate field: <code>total</code>:</p>
<pre><pre class="playground"><code class="language-rust"><span class="boring">#![allow(unused)]
</span><span class="boring">fn main() {
</span>table
.has_many("line_items", "order_id", || Box::new(LineItem::table()))
.with_expression("total", |t| {
let item = t.sub_line_items();
item.sum(item.total()).render_chunk()
})
<span class="boring">}</span></code></pre></pre>
<p>Lets examine more generally what is happening here. Use of <code>has_many</code> creates</p>
<p>This is a very simple example of a lazy expression field. It is a field that is calculated
by a closure. The closure is passed a reference to the table. The closure can then use
the table to create a new field.</p>
<p>The above example is equivalent to this SQL:</p>
<pre><code class="language-sql">SELECT id,
(SELECT SUM((SELECT price FROM product WHERE id = product_id) * quantity)
FROM order_line WHERE order_line.order_id = ord.id) AS total
FROM ord
</code></pre>
<p>In this example, we are using a sub-query to calculate the total. The sub-query is
created by calling <code>sub_line_items()</code> on the table. This method returns a new table
that is a subset of the original table. The sub-query is then used to create a new
field called <code>total</code> that is a sum of the price and quantity.</p>
<p>The implementation
of <code>sql::Table</code> however provides ability to create new Data Sets from existing ones.</p>

</main>

<nav class="nav-wrapper" aria-label="Page navigation">
<!-- Mobile navigation buttons -->
<a rel="prev" href="introduction.html" class="mobile-nav-chapters previous" title="Previous chapter" aria-label="Previous chapter" aria-keyshortcuts="Left">
<i class="fa fa-angle-left"></i>
</a>

<a rel="next prefetch" href="1-table-and-fields.html" class="mobile-nav-chapters next" title="Next chapter" aria-label="Next chapter" aria-keyshortcuts="Right">
<i class="fa fa-angle-right"></i>
</a>

<div style="clear: both"></div>
</nav>
</div>
</div>

<nav class="nav-wide-wrapper" aria-label="Page navigation">
<a rel="prev" href="introduction.html" class="nav-chapters previous" title="Previous chapter" aria-label="Previous chapter" aria-keyshortcuts="Left">
<i class="fa fa-angle-left"></i>
</a>

<a rel="next prefetch" href="1-table-and-fields.html" class="nav-chapters next" title="Next chapter" aria-label="Next chapter" aria-keyshortcuts="Right">
<i class="fa fa-angle-right"></i>
</a>
</nav>

</div>




<script>
window.playground_copyable = true;
</script>


<script src="elasticlunr.min.js"></script>
<script src="mark.min.js"></script>
<script src="searcher.js"></script>

<script src="clipboard.min.js"></script>
<script src="highlight.js"></script>
<script src="book.js"></script>

<!-- Custom JS scripts -->


</div>
</body>
</html>
4 changes: 2 additions & 2 deletions 1-table-and-fields.html
Original file line number Diff line number Diff line change
Expand Up @@ -271,7 +271,7 @@ <h2 id="what-exactly-is-a-field"><a class="header" href="#what-exactly-is-a-fiel

<nav class="nav-wrapper" aria-label="Page navigation">
<!-- Mobile navigation buttons -->
<a rel="prev" href="introduction.html" class="mobile-nav-chapters previous" title="Previous chapter" aria-label="Previous chapter" aria-keyshortcuts="Left">
<a rel="prev" href="1-dataset.html" class="mobile-nav-chapters previous" title="Previous chapter" aria-label="Previous chapter" aria-keyshortcuts="Left">
<i class="fa fa-angle-left"></i>
</a>

Expand All @@ -285,7 +285,7 @@ <h2 id="what-exactly-is-a-field"><a class="header" href="#what-exactly-is-a-fiel
</div>

<nav class="nav-wide-wrapper" aria-label="Page navigation">
<a rel="prev" href="introduction.html" class="nav-chapters previous" title="Previous chapter" aria-label="Previous chapter" aria-keyshortcuts="Left">
<a rel="prev" href="1-dataset.html" class="nav-chapters previous" title="Previous chapter" aria-label="Previous chapter" aria-keyshortcuts="Left">
<i class="fa fa-angle-left"></i>
</a>

Expand Down
Loading

0 comments on commit 8d50df9

Please sign in to comment.