GitHub Pages with jekyll

This commit is contained in:
Simon Binder 2019-04-02 19:26:48 +02:00
parent 040f54d004
commit cc46cd9a5b
No known key found for this signature in database
GPG Key ID: B807FDF954BA00CF
16 changed files with 842 additions and 0 deletions

3
docs/.gitignore vendored Normal file
View File

@ -0,0 +1,3 @@
_site
.sass-cache
.jekyll-metadata

12
docs/404.html Normal file
View File

@ -0,0 +1,12 @@
---
layout: default
title: Page not found
permalink: /404
nav_exclude: true
search_exclude: true
exclude: true
---
<h1>Page not found</h1>
<p>The page you requested could not be found. Try using the navigation {% if site.search_enabled %}or search {% endif %}to find what you're looking for or go to this <a href="{{ site.url }}{{ site.baseurl }}">site's home page</a>.</p>

23
docs/Gemfile Normal file
View File

@ -0,0 +1,23 @@
source "https://rubygems.org"
# Hello! This is where you manage which Jekyll version is used to run.
# When you want to use a different version, change it below, save the
# file and run `bundle install`. Run Jekyll with `bundle exec`, like so:
#
# bundle exec jekyll serve
#
# This will help ensure the proper Jekyll version is running.
# Happy Jekylling!
gem "just-the-docs"
# If you want to use GitHub Pages, remove the "gem "jekyll"" above and
# uncomment the line below. To upgrade, run `bundle update github-pages`.
gem "github-pages", group: :jekyll_plugins
# Windows does not include zoneinfo files, so bundle the tzinfo-data gem
gem "tzinfo-data", platforms: [:mingw, :mswin, :x64_mingw, :jruby]
# Performance-booster for watching directories on Windows
gem "wdm", "~> 0.1.0" if Gem.win_platform?

254
docs/Gemfile.lock Normal file
View File

@ -0,0 +1,254 @@
GEM
remote: https://rubygems.org/
specs:
activesupport (4.2.10)
i18n (~> 0.7)
minitest (~> 5.1)
thread_safe (~> 0.3, >= 0.3.4)
tzinfo (~> 1.1)
addressable (2.5.2)
public_suffix (>= 2.0.2, < 4.0)
coffee-script (2.4.1)
coffee-script-source
execjs
coffee-script-source (1.11.1)
colorator (1.1.0)
commonmarker (0.17.13)
ruby-enum (~> 0.5)
concurrent-ruby (1.1.5)
dnsruby (1.61.2)
addressable (~> 2.5)
em-websocket (0.5.1)
eventmachine (>= 0.12.9)
http_parser.rb (~> 0.6.0)
ethon (0.12.0)
ffi (>= 1.3.0)
eventmachine (1.2.7)
execjs (2.7.0)
faraday (0.15.4)
multipart-post (>= 1.2, < 3)
ffi (1.10.0)
forwardable-extended (2.6.0)
gemoji (3.0.0)
github-pages (197)
activesupport (= 4.2.10)
github-pages-health-check (= 1.16.1)
jekyll (= 3.7.4)
jekyll-avatar (= 0.6.0)
jekyll-coffeescript (= 1.1.1)
jekyll-commonmark-ghpages (= 0.1.5)
jekyll-default-layout (= 0.1.4)
jekyll-feed (= 0.11.0)
jekyll-gist (= 1.5.0)
jekyll-github-metadata (= 2.12.1)
jekyll-mentions (= 1.4.1)
jekyll-optional-front-matter (= 0.3.0)
jekyll-paginate (= 1.1.0)
jekyll-readme-index (= 0.2.0)
jekyll-redirect-from (= 0.14.0)
jekyll-relative-links (= 0.6.0)
jekyll-remote-theme (= 0.3.1)
jekyll-sass-converter (= 1.5.2)
jekyll-seo-tag (= 2.5.0)
jekyll-sitemap (= 1.2.0)
jekyll-swiss (= 0.4.0)
jekyll-theme-architect (= 0.1.1)
jekyll-theme-cayman (= 0.1.1)
jekyll-theme-dinky (= 0.1.1)
jekyll-theme-hacker (= 0.1.1)
jekyll-theme-leap-day (= 0.1.1)
jekyll-theme-merlot (= 0.1.1)
jekyll-theme-midnight (= 0.1.1)
jekyll-theme-minimal (= 0.1.1)
jekyll-theme-modernist (= 0.1.1)
jekyll-theme-primer (= 0.5.3)
jekyll-theme-slate (= 0.1.1)
jekyll-theme-tactile (= 0.1.1)
jekyll-theme-time-machine (= 0.1.1)
jekyll-titles-from-headings (= 0.5.1)
jemoji (= 0.10.2)
kramdown (= 1.17.0)
liquid (= 4.0.0)
listen (= 3.1.5)
mercenary (~> 0.3)
minima (= 2.5.0)
nokogiri (>= 1.8.5, < 2.0)
rouge (= 2.2.1)
terminal-table (~> 1.4)
github-pages-health-check (1.16.1)
addressable (~> 2.3)
dnsruby (~> 1.60)
octokit (~> 4.0)
public_suffix (~> 3.0)
typhoeus (~> 1.3)
html-pipeline (2.10.0)
activesupport (>= 2)
nokogiri (>= 1.4)
http_parser.rb (0.6.0)
i18n (0.9.5)
concurrent-ruby (~> 1.0)
jekyll (3.7.4)
addressable (~> 2.4)
colorator (~> 1.0)
em-websocket (~> 0.5)
i18n (~> 0.7)
jekyll-sass-converter (~> 1.0)
jekyll-watch (~> 2.0)
kramdown (~> 1.14)
liquid (~> 4.0)
mercenary (~> 0.3.3)
pathutil (~> 0.9)
rouge (>= 1.7, < 4)
safe_yaml (~> 1.0)
jekyll-avatar (0.6.0)
jekyll (~> 3.0)
jekyll-coffeescript (1.1.1)
coffee-script (~> 2.2)
coffee-script-source (~> 1.11.1)
jekyll-commonmark (1.3.1)
commonmarker (~> 0.14)
jekyll (>= 3.7, < 5.0)
jekyll-commonmark-ghpages (0.1.5)
commonmarker (~> 0.17.6)
jekyll-commonmark (~> 1)
rouge (~> 2)
jekyll-default-layout (0.1.4)
jekyll (~> 3.0)
jekyll-feed (0.11.0)
jekyll (~> 3.3)
jekyll-gist (1.5.0)
octokit (~> 4.2)
jekyll-github-metadata (2.12.1)
jekyll (~> 3.4)
octokit (~> 4.0, != 4.4.0)
jekyll-mentions (1.4.1)
html-pipeline (~> 2.3)
jekyll (~> 3.0)
jekyll-optional-front-matter (0.3.0)
jekyll (~> 3.0)
jekyll-paginate (1.1.0)
jekyll-readme-index (0.2.0)
jekyll (~> 3.0)
jekyll-redirect-from (0.14.0)
jekyll (~> 3.3)
jekyll-relative-links (0.6.0)
jekyll (~> 3.3)
jekyll-remote-theme (0.3.1)
jekyll (~> 3.5)
rubyzip (>= 1.2.1, < 3.0)
jekyll-sass-converter (1.5.2)
sass (~> 3.4)
jekyll-seo-tag (2.5.0)
jekyll (~> 3.3)
jekyll-sitemap (1.2.0)
jekyll (~> 3.3)
jekyll-swiss (0.4.0)
jekyll-theme-architect (0.1.1)
jekyll (~> 3.5)
jekyll-seo-tag (~> 2.0)
jekyll-theme-cayman (0.1.1)
jekyll (~> 3.5)
jekyll-seo-tag (~> 2.0)
jekyll-theme-dinky (0.1.1)
jekyll (~> 3.5)
jekyll-seo-tag (~> 2.0)
jekyll-theme-hacker (0.1.1)
jekyll (~> 3.5)
jekyll-seo-tag (~> 2.0)
jekyll-theme-leap-day (0.1.1)
jekyll (~> 3.5)
jekyll-seo-tag (~> 2.0)
jekyll-theme-merlot (0.1.1)
jekyll (~> 3.5)
jekyll-seo-tag (~> 2.0)
jekyll-theme-midnight (0.1.1)
jekyll (~> 3.5)
jekyll-seo-tag (~> 2.0)
jekyll-theme-minimal (0.1.1)
jekyll (~> 3.5)
jekyll-seo-tag (~> 2.0)
jekyll-theme-modernist (0.1.1)
jekyll (~> 3.5)
jekyll-seo-tag (~> 2.0)
jekyll-theme-primer (0.5.3)
jekyll (~> 3.5)
jekyll-github-metadata (~> 2.9)
jekyll-seo-tag (~> 2.0)
jekyll-theme-slate (0.1.1)
jekyll (~> 3.5)
jekyll-seo-tag (~> 2.0)
jekyll-theme-tactile (0.1.1)
jekyll (~> 3.5)
jekyll-seo-tag (~> 2.0)
jekyll-theme-time-machine (0.1.1)
jekyll (~> 3.5)
jekyll-seo-tag (~> 2.0)
jekyll-titles-from-headings (0.5.1)
jekyll (~> 3.3)
jekyll-watch (2.2.1)
listen (~> 3.0)
jemoji (0.10.2)
gemoji (~> 3.0)
html-pipeline (~> 2.2)
jekyll (~> 3.0)
just-the-docs (0.1.6)
jekyll (~> 3.3)
rake (~> 10.0)
kramdown (1.17.0)
liquid (4.0.0)
listen (3.1.5)
rb-fsevent (~> 0.9, >= 0.9.4)
rb-inotify (~> 0.9, >= 0.9.7)
ruby_dep (~> 1.2)
mercenary (0.3.6)
mini_portile2 (2.4.0)
minima (2.5.0)
jekyll (~> 3.5)
jekyll-feed (~> 0.9)
jekyll-seo-tag (~> 2.1)
minitest (5.11.3)
multipart-post (2.0.0)
nokogiri (1.10.2)
mini_portile2 (~> 2.4.0)
octokit (4.14.0)
sawyer (~> 0.8.0, >= 0.5.3)
pathutil (0.16.2)
forwardable-extended (~> 2.6)
public_suffix (3.0.3)
rake (10.5.0)
rb-fsevent (0.10.3)
rb-inotify (0.10.0)
ffi (~> 1.0)
rouge (2.2.1)
ruby-enum (0.7.2)
i18n
ruby_dep (1.5.0)
rubyzip (1.2.2)
safe_yaml (1.0.5)
sass (3.7.3)
sass-listen (~> 4.0.0)
sass-listen (4.0.0)
rb-fsevent (~> 0.9, >= 0.9.4)
rb-inotify (~> 0.9, >= 0.9.7)
sawyer (0.8.1)
addressable (>= 2.3.5, < 2.6)
faraday (~> 0.8, < 1.0)
terminal-table (1.8.0)
unicode-display_width (~> 1.1, >= 1.1.1)
thread_safe (0.3.6)
typhoeus (1.3.1)
ethon (>= 0.9.0)
tzinfo (1.2.5)
thread_safe (~> 0.1)
unicode-display_width (1.5.0)
PLATFORMS
ruby
DEPENDENCIES
github-pages
just-the-docs
tzinfo-data
BUNDLED WITH
2.0.1

44
docs/_config.yml Normal file
View File

@ -0,0 +1,44 @@
# Welcome to Jekyll!
#
# This config file is meant for settings that affect your whole blog, values
# which you are expected to set up once and rarely edit after that. If you find
# yourself editing this file very often, consider using Jekyll's data files
# feature for the data you need to update frequently.
#
# For technical reasons, this file is *NOT* reloaded automatically when you use
# 'bundle exec jekyll serve'. If you change this file, please restart the server process.
# Site settings
# These are used to personalize your new site. If you look in the HTML files,
# you will see them accessed via {{ site.title }}, {{ site.email }}, and so on.
# You can create any custom variable you would like, and they will be accessible
# in the templates via {{ site.myvariable }}.
title: Moor
#email: your-email@example.com
description: >- # this means to ignore newlines until "baseurl:"
Moor is an easy to use, reactive, typesafe persistence library for Flutter apps.
baseurl: "/moor" # the subpath of your site, e.g. /blog
url: "https://simolus3.github.io" # the base hostname & protocol for your site, e.g. http://example.com
#twitter_username: jekyllrb
github_link: https://github.com/simolus3/moor
search_enabled: true
# Build settings
markdown: kramdown
theme: just-the-docs
plugins:
- jekyll-feed
# Exclude from processing.
# The following items will not be processed, by default. Create a custom list
# to override the default setting.
# exclude:
# - Gemfile
# - Gemfile.lock
# - node_modules
# - vendor/bundle/
# - vendor/cache/
# - vendor/gems/
# - vendor/ruby/

View File

@ -0,0 +1,76 @@
### Adding the dependency
First, let's add moor to your project's `pubspec.yaml`.
At the moment, the current version of `moor_flutter` is [![Flutter version](https://img.shields.io/pub/v/moor_flutter.svg)](https://pub.dartlang.org/packages/moor_flutter) and the current version of `moor_generator` is [![Generator version](https://img.shields.io/pub/v/moor_generator.svg)](https://pub.dartlang.org/packages/moor_generator)
```yaml
dependencies:
moor_flutter: # use the latest version
dev_dependencies:
moor_generator: # use the latest version
build_runner:
```
We're going to use the `moor_flutter` library to specify tables and access the database. The
`moor_generator` library will take care of generating the necessary code so the
library knows how your table structure looks like.
### Declaring tables
Using moor, you can model the structure of your tables with simple dart code:
```dart
import 'package:moor_flutter/moor_flutter.dart';
// assuming that your file is called filename.dart. This will give an error at first,
// but it's needed for moor to know about the generated code
part 'filename.g.dart';
// this will generate a table called "todos" for us. The rows of that table will
// be represented by a class called "Todo".
class Todos extends Table {
IntColumn get id => integer().autoIncrement()();
TextColumn get title => text().withLength(min: 6, max: 10)();
TextColumn get content => text().named('body')();
IntColumn get category => integer().nullable()();
}
// This will make moor generate a class called "Category" to represent a row in this table.
// By default, "Categorie" would have been used because it only strips away the trailing "s"
// in the table name.
@DataClassName("Category")
class Categories extends Table {
IntColumn get id => integer().autoIncrement()();
TextColumn get description => text()();
}
// this annotation tells moor to prepare a database class that uses both of the
// tables we just defined. We'll see how to use that database class in a moment.
@UseMoor(tables: [Todos, Categories])
class MyDatabase {
}
```
__⚠ Note:__ The column definitions, the table name and the primary key must be known at
compile time. For column definitions and the primary key, the function must use the `=>`
operator and can't contain anything more than what's included in this `readme` and the
examples. Otherwise, the generator won't be able to know what's going on.
### Generating the code
Moor integrates with the dart `build` system, so you can generate all the code needed with
`flutter packages pub run build_runner build`. If you want to continously rebuild the generated code
whever you change your code, run `flutter packages pub run build_runner watch` instead.
After running either command once, the moor generator will have created a class for your
database and data classes for your entities. To use it, change the `MyDatabase` class as
follows:
```dart
@UseMoor(tables: [Todos, Categories])
class MyDatabase extends _$MyDatabase {
// we tell the database where to store the data with this constructor
MyDatabase() : super(FlutterQueryExecutor.inDatabaseFolder(path: 'db.sqlite'));
// you should bump this number whenever you change or add a table definition. Migrations
// are covered later in this readme.
@override
int get schemaVersion => 1;
}
```

44
docs/_includes/nav.html Normal file
View File

@ -0,0 +1,44 @@
<nav role="navigation" aria-label="Main navigation">
<ul class="navigation-list">
{% assign pages_list = site.html_pages | sort:"nav_order" %}
{% for node in pages_list %}
{% unless node.nav_exclude %}
{% if node.parent == nil %}
<li class="navigation-list-item{% if page.url == node.url or page.parent == node.title or page.grand_parent == node.title %} active{% endif %}">
{% if page.parent == node.title or page.grand_parent == node.title %}
{% assign first_level_url = node.url | absolute_url %}
{% endif %}
<a href="{{ node.url | absolute_url }}" class="navigation-list-link{% if page.url == node.url %} active{% endif %}">{{ node.title }}</a>
{% if node.has_children %}
{% assign children_list = site.html_pages | sort:"nav_order" %}
<ul class="navigation-list-child-list ">
{% for child in children_list %}
{% if child.parent == node.title %}
<li class="navigation-list-item {% if page.url == child.url or page.parent == child.title %} active{% endif %}">
{% if page.url == child.url or page.parent == child.title %}
{% assign second_level_url = child.url | absolute_url %}
{% endif %}
<a href="{{ child.url | absolute_url }}" class="navigation-list-link{% if page.url == child.url %} active{% endif %}">{{ child.title }}</a>
{% if child.has_children %}
{% assign grand_children_list = site.html_pages | sort:"nav_order" %}
<ul class="navigation-list-child-list">
{% for grand_child in grand_children_list %}
{% if grand_child.parent == child.title %}
<li class="navigation-list-item {% if page.url == grand_child.url %} active{% endif %}">
<a href="{{ grand_child.url | absolute_url }}" class="navigation-list-link{% if page.url == grand_child.url %} active{% endif %}">{{ grand_child.title }}</a>
</li>
{% endif %}
{% endfor %}
</ul>
{% endif %}
</li>
{% endif %}
{% endfor %}
</ul>
{% endif %}
</li>
{% endif %}
{% endunless %}
{% endfor %}
</ul>
</nav>

View File

@ -0,0 +1,83 @@
<!DOCTYPE html>
<html lang="en-us">
{% include head.html %}
<body>
<div class="page-wrap">
<div class="side-bar">
<a href="{{ site.url }}{{ site.baseurl }}" class="site-title fs-6 lh-tight">{{ site.title }}</a>
<span class="fs-3"><button class="js-main-nav-trigger navigation-list-toggle btn btn-outline" type="button" data-text-toggle="Hide">Menu</button></span>
<div class="navigation main-nav js-main-nav">
{% include nav.html %}
</div>
<footer role="contentinfo" class="site-footer">
<p class="text-small text-grey-dk-000 mb-0">This site uses <a href="https://github.com/pmarsceill/just-the-docs">Just the Docs</a>, a documentation theme for Jekyll.</p>
</footer>
</div>
<div class="main-content-wrap js-main-content" tabindex="0">
<div class="page-header">
<div class="main-content">
{% if site.search_enabled != nil %}
<div class="search js-search">
<div class="search-input-wrap">
<input type="text" class="js-search-input search-input" tabindex="0" placeholder="Search {{ site.title }}" aria-label="Search {{ site.title }}" autocomplete="off">
<svg width="14" height="14" viewBox="0 0 28 28" xmlns="http://www.w3.org/2000/svg" class="search-icon"><title>Search</title><g fill-rule="nonzero"><path d="M17.332 20.735c-5.537 0-10-4.6-10-10.247 0-5.646 4.463-10.247 10-10.247 5.536 0 10 4.601 10 10.247s-4.464 10.247-10 10.247zm0-4c3.3 0 6-2.783 6-6.247 0-3.463-2.7-6.247-6-6.247s-6 2.784-6 6.247c0 3.464 2.7 6.247 6 6.247z"/><path d="M11.672 13.791L.192 25.271 3.02 28.1 14.5 16.62z"/></g></svg>
</div>
<div class="js-search-results search-results-wrap"></div>
</div>
{% endif %}
{% comment %} Changes from upstream here to include pub badge {% endcomment %}
<ul class="list-style-none text-small mt-md-1 mb-md-1 pb-4 pb-md-0 js-aux-nav aux-nav">
<li><a href="https://pub.dartlang.org/packages/moor_flutter"><img src="https://img.shields.io/pub/v/moor_flutter.svg" /></a></li>
</ul>
</div>
</div>
<div class="main-content">
{% unless page.url == "/" %}
{% if page.parent %}
<nav class="breadcrumb-nav">
<ol class="breadcrumb-nav-list">
{% if page.grand_parent %}
<li class="breadcrumb-nav-list-item"><a href="{{ first_level_url }}">{{ page.grand_parent }}</a></li>
<li class="breadcrumb-nav-list-item"><a href="{{ second_level_url }}">{{ page.parent }}</a></li>
{% else %}
<li class="breadcrumb-nav-list-item"><a href="{{ first_level_url }}">{{ page.parent }}</a></li>
{% endif %}
<li class="breadcrumb-nav-list-item"><span>{{ page.title }}</span></li>
</ol>
</nav>
{% endif %}
{% endunless %}
<div id="main-content" class="page-content" role="main">
{{ content }}
{% if page.has_children == true and page.has_toc != false %}
<hr>
<h2 class="text-delta">Table of contents</h2>
{% assign children_list = site.pages | sort:"nav_order" %}
<ul>
{% for child in children_list %}
{% if child.parent == page.title and child.title != page.title %}
<li>
<a href="{{ child.url | absolute_url }}">{{ child.title }}</a>
</li>
{% endif %}
{% endfor %}
</ul>
{% endif %}
<hr>
<span class="fs-2">
Was this page helpful? Please
{% assign body= "From documentation site " %}
<a href="{{site.github_link}}/issues/new?body={{ body | url_encode }}{{page.path | url_encode}}">report an issue</a>
if you have questions or problems.
</span>
</div>
</div>
</div>
</div>
</body>
</html>

View File

@ -0,0 +1,8 @@
---
layout: default
---
{% if page.since != nil %}
<span class="label label-green">Available from {{page.since}}</span>
{% endif %}
{{ content }}

35
docs/docs/daos.md Normal file
View File

@ -0,0 +1,35 @@
---
layout: post
title: Modularity with DAOs
nav_order: 5
permalink: /daos/
---
# Extracting functionality with DAOs
When you have a lot of queries, putting them all into one class quickly becomes
tedious. You can avoid this by extracting some queries into classes that are
available from your main database class. Consider the following code:
```dart
part 'todos_dao.g.dart';
// the _TodosDaoMixin will be created by moor. It contains all the necessary
// fields for the tables. The <MyDatabase> type annotation is the database class
// that should use this dao.
@UseDao(tables: [Todos])
class TodosDao extends DatabaseAccessor<MyDatabase> with _TodosDaoMixin {
// this constructor is required so that the main database can create an instance
// of this object.
TodosDao(MyDatabase db) : super(db);
Stream<List<TodoEntry>> todosInCategory(Category category) {
if (category == null) {
return (select(todos)..where((t) => isNull(t.category))).watch();
} else {
return (select(todos)..where((t) => t.category.equals(category.id)))
.watch();
}
}
}
```
If we now change the annotation on the `MyDatabase` class to `@UseMoor(tables: [Todos, Categories], daos: [TodosDao])`
and re-run the code generation, a generated getter `todosDao` can be used to access the instance of that dao.

View File

@ -0,0 +1,11 @@
---
layout: post
title: Getting started
nav_order: 1
permalink: /getting-started/
---
# Getting started
{% include content/getting_started.md %}
Congrats, you are now ready to fully use moor and [write queries]({{site.url}}/writing-queries/).

43
docs/docs/migrations.md Normal file
View File

@ -0,0 +1,43 @@
---
layout: post
title: Migrations
nav_order: 4
permalink: /migrations/
---
# Migrations
Moor provides a migration API that can be used to gradually apply schema changes after bumping
the `schemaVersion` getter inside the `Database` class. To use it, override the `migration`
getter. Here's an example: Let's say you wanted to add a due date to your todo entries:
```dart
class Todos extends Table {
IntColumn get id => integer().autoIncrement()();
TextColumn get title => text().withLength(min: 6, max: 10)();
TextColumn get content => text().named('body')();
IntColumn get category => integer().nullable()();
DateTimeColumn get dueDate => dateTime().nullable()(); // we just added this column
}
```
We can now change the `database` class like this:
```dart
@override
int get schemaVersion => 2; // bump because the tables have changed
@override
MigrationStrategy get migration => MigrationStrategy(
onCreate: (Migrator m) {
return m.createAllTables();
},
onUpgrade: (Migrator m, int from, int to) async {
if (from == 1) {
// we added the dueDate property in the change from version 1
await m.addColumn(todos, todos.dueDate);
}
}
);
// rest of class can stay the same
```
You can also add individual tables or drop them. You can't use the high-level query API in
migrations. If you need to use it, please specify the `onFinished` method on the
`MigrationStrategy`. It will be called after a migration happened and it's safe to call methods
on your database from inside that method.

View File

@ -0,0 +1,9 @@
---
layout: feature
title: Transactions
nav_order: 3
since: 1.1
---
# Transactions
TBD

View File

@ -0,0 +1,37 @@
---
layout: post
title: Custom queries
parent: Writing queries
---
# Custom statements
You can also issue custom queries by calling `customUpdate` for update and deletes and
`customSelect` or `customSelectStream` for select statements. Using the todo example
above, here is a simple custom query that loads all categories and how many items are
in each category:
```dart
class CategoryWithCount {
final Category category;
final int count; // amount of entries in this category
CategoryWithCount(this.category, this.count);
}
// then, in the database class:
Stream<List<CategoryWithCount>> categoriesWithCount() {
// select all categories and load how many associated entries there are for
// each category
return customSelectStream(
'SELECT *, (SELECT COUNT(*) FROM todos WHERE category = c.id) AS "amount" FROM categories c;',
readsFrom: {todos, categories}).map((rows) {
// when we have the result set, map each row to the data class
return rows
.map((row) => CategoryWithCount(Category.fromData(row.data, this), row.readInt('amount')))
.toList();
});
}
```
For custom selects, you should use the `readsFrom` parameter to specify from which tables the query is
reading. When using a `Stream`, moor will be able to know after which updates the stream should emit
items. If you're using a custom query for updates or deletes with `customUpdate`, you should also
use the `updates` parameter to let moor know which tables you're touching.

View File

@ -0,0 +1,107 @@
---
layout: post
title: Writing queries
nav_order: 2
has_children: true
permalink: /writing-queries/
---
__Note__: This assumes that you already have your database class ready.
Follow the [instructions][getting-started] over here on how to do that.
# Writing queries
The examples here use the tables defined [here][getting-started].
For each table you've specified in the `@UseMoor` annotation on your database class,
a corresponding getter for a table will be generated. That getter can be used to
run statements:
```dart
// inside the database class, the `todos` getter has been created by moor.
// loads all todo entries
Future<List<Todo>> get allTodoEntries => select(todos).get();
// watches all todo entries in a given category. The stream will automatically
// emit new items whenever the underlying data changes.
Stream<List<TodoEntry>> watchEntriesInCategory(Category c) {
return (select(todos)..where((t) => t.category.equals(c.id))).watch();
}
```
## Select statements
You can create `select` statements by starting them with `select(tableName)`, where the
table name
is a field generated for you by moor. Each table used in a database will have a matching field
to run queries against. Any query can be run once with `get()` or be turned into an auto-updating
stream using `watch()`.
### Where
You can apply filters to a query by calling `where()`. The where method takes a function that
should map the given table to an `Expression` of boolean. A common way to create such expression
is by using `equals` on expressions. Integer columns can also be compared with `isBiggerThan`
and `isSmallerThan`. You can compose expressions using `and(a, b), or(a, b)` and `not(a)`.
### Limit
You can limit the amount of results returned by calling `limit` on queries. The method accepts
the amount of rows to return and an optional offset.
### Ordering
You can use the `orderBy` method on the select statement. It expects a list of functions that extract the individual
ordering terms from the table.
```dart
Future<List<TodoEntry>> sortEntriesAlphabetically() {
return (select(todos)..orderBy([(t) => OrderingTerm(expression: t.title)])).get();
}
```
You can also reverse the order by setting the `mode` property of the `OrderingTerm` to
`OrderingMode.desc`.
## Updates and deletes
You can use the generated `row` class to update individual fields of any row:
```dart
Future moveImportantTasksIntoCategory(Category target) {
// use update(...).write when you have a custom where clause and want to update
// only the columns that you specify (here, only "category" will be updated, the
// title and description of the rows affected will be left unchanged).
// Notice that you can't set fields back to null with this method.
return (update(todos)
..where((t) => t.title.like('%Important%'))
).write(TodoEntry(
category: target.id
),
);
}
Future update(TodoEntry entry) {
// using replace will update all fields from the entry that are not marked as a primary key.
// it will also make sure that only the entry with the same primary key will be updated.
// Here, this means that the row that has the same id as entry will be updated to reflect
// the entry's title, content and category. Unlike write, this supports setting columns back
// to null. As it set's its where clause automatically, it can not be used together with where.
return update(todos).replace(entry);
}
Future feelingLazy() {
// delete the oldest nine entries
return (delete(todos)..where((t) => t.id.isSmallerThanValue(10))).go();
}
```
__⚠ Caution:__ If you don't explicitly add a `where` clause on updates or deletes,
the statement will affect all rows in the table!
## Inserts
You can very easily insert any valid object into tables:
```dart
// returns the generated id
Future<int> addTodoEntry(Todo entry) {
return into(todos).insert(entry);
}
```
All row classes generated will have a constructor that can be used to create objects:
```dart
addTodoEntry(
Todo(
title: 'Important task',
content: 'Refactor persistence code',
),
);
```
If a column is nullable or has a default value (this includes auto-increments), the field
can be omitted. All other fields must be set and non-null. The `insert` method will throw
otherwise.
[getting-started]: {{ "/getting-started" | absolute_url }}

53
docs/index.md Normal file
View File

@ -0,0 +1,53 @@
---
layout: home
title: Home
nav_order: 0
---
# Moor
{: .fs-9 }
Moor is an easy to use, reactive persistence library for Flutter apps. Define your
database tables in pure Dart and enjoy a fluent query API, auto-updating streams
and more!
{: .fs-6 .fw-300 }
[![Build Status](https://travis-ci.com/simolus3/moor.svg?token=u4VnFEE5xnWVvkE6QsqL&branch=master)](https://travis-ci.com/simolus3/moor)
[![codecov](https://codecov.io/gh/simolus3/moor/branch/master/graph/badge.svg)](https://codecov.io/gh/simolus3/moor)
[Get started now]({{site.url}}/getting-started/){: .btn .btn-green .fs-5 .mb-4 .mb-md-0 .mr-2 }
[View on GitHub]({{site.github_link}}){: .btn .btn-outline .fs-5 .mb-4 .mb-md-0 .mr-2 }
---
## Getting started
{% include content/getting_started.md %}
You can ignore the `schemaVersion` at the moment, the important part is that you can
now run your queries with fluent Dart code:
## TODO-List and current limitations
### Limitations (at the moment)
Please note that a workaround for most on this list exists with custom statements.
- No `group by` or window functions
### Planned for the future
These aren't sorted by priority. If you have more ideas or want some features happening soon,
let me know by creating an issue!
- Simple `COUNT(*)` operations (group operations will be much more complicated)
- Support Dart VM apps
- References
- DSL API
- Support in generator
- Validations
- Bulk inserts
- When inserts / updates fail due to invalid data, explain why that happened
### Interesting stuff that would be nice to have
Implementing this will very likely result in backwards-incompatible changes.
- Find a way to hide implementation details from users while still making them
accessible for the generated code
- `GROUP BY` grouping functions
- Support for different database engines
- Support webapps via `AlaSQL` or a different engine