Skip to content

Commit

Permalink
Merge pull request #100 from cyjake/docs-v1.x-changes
Browse files Browse the repository at this point in the history
docs: init migrations, validations, hooks, and sequelize adapter pages
  • Loading branch information
JimmyDaddy authored Mar 18, 2021
2 parents 05bcba1 + e207856 commit 0207011
Show file tree
Hide file tree
Showing 22 changed files with 335 additions and 118 deletions.
37 changes: 21 additions & 16 deletions Readme.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# Leoric

[![NPM Downloads](https://img.shields.io/npm/dm/oceanify.svg?style=flat)](https://www.npmjs.com/package/leoric)
[![NPM Downloads](https://img.shields.io/npm/dm/leoric.svg?style=flat)](https://www.npmjs.com/package/leoric)
[![NPM Version](http://img.shields.io/npm/v/leoric.svg?style=flat)](https://www.npmjs.com/package/leoric)
[![Build Status](https://travis-ci.org/cyjake/leoric.svg)](https://travis-ci.org/cyjake/leoric)
[![Coverage Status](https://coveralls.io/repos/github/cyjake/leoric/badge.svg?branch=master)](https://coveralls.io/github/cyjake/leoric?branch=master)
Expand All @@ -9,7 +9,7 @@ Leoric is an object-relational mapping for Node.js, which is heavily influenced

## Usage

Assume the tables of posts, users, and comments were setup already. We may declare the models as classes by extending from the base class `Bone` of Leoric. After the models are `connect`ed to the database, the columns of the tables are mapped as attributes, the associations are setup, feel free to start querying.
Assume the tables of posts, users, and comments were setup already. We may declare the models as classes by extending from the base class `Bone` of Leoric. After the models are connected to the database, the columns of the tables are mapped as attributes, the associations are setup, feel free to start querying.

```js
const { Bone, connect } = require('leoric')
Expand All @@ -24,7 +24,7 @@ class Post extends Bone {

async function main() {
// connect models to database
await connect({ host: 'example.com', models: [Post], /* among other options */ })
await connect({ host: 'example.com', models: [ Post ], /* among other options */ })

// CRUD
await Post.create({ title: 'New Post' })
Expand All @@ -41,13 +41,29 @@ async function main() {
}
```

If table structures were intended to be maintained in the models, Leoric can be used as a table migration tool as well. We can just define attributes in the models, and call `realm.sync()` whenever we are ready.

```js
const { BIGINT, STRING } = Bone.DataTypes;
class Post extends Bone {
static attributes = {
id: { type: BIGINT, primayKey: true },
email: { type: STRING, allowNull: false },
nickname: { type: STRING, allowNull: false },
}
}

const realm = new Realm({ models: [ Post ] });
await realm.sync();
```

## Syntax Table

| JavaScript | SQL |
|-----------------------------------------|----------------------------------------------------|
| `Post.create({ title: 'New Post' })` | `INSERT INTO posts (title) VALUES ('New Post')` |
| `Post.create({ title: 'New Post' })` | `INSERT INTO posts (title) VALUES ('New Post')` |
| `Post.all` | `SELECT * FROM posts` |
| `Post.find({ title: 'New Post' })` | `SELECT * FROM posts WHERE title = 'New Post'` |
| `Post.find({ title: 'New Post' })` | `SELECT * FROM posts WHERE title = 'New Post'` |
| `Post.find(42)` | `SELECT * FROM posts WHERE id = 42` |
| `Post.order('title')` | `SELECT * FROM posts ORDER BY title` |
| `Post.order('title', 'desc')` | `SELECT * FROM posts ORDER BY title DESC` |
Expand All @@ -56,14 +72,3 @@ async function main() {
| `Post.remove({ id: 42 })` | `DELETE FROM posts WHERE id = 42` |

A more detailed syntax table may be found at the [documentation](http://cyj.me/leoric/#syntax-table) site.

## Migrations

Currently, Leoric doesn't provide a way to do database migrations. There are two popular approaches:

- A separated migration DSL and database metadata, like Active Record.
- A detailed enumeration of attributes and types in the models, like Django.

There is a third way, which is the very reason Leoric has yet to implement migrations, which is that the database can be designed through a third-party service. It can be an ER designer, a GUI software for MySQL, or a MySQL-compliant database in the cloud.

But I'm sure we'll get to that.
2 changes: 2 additions & 0 deletions docs/Gemfile
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,5 @@ source "https://rubygems.org"
# 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

gem "webrick", "~> 1.7"
4 changes: 4 additions & 0 deletions docs/_layouts/en.html
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,12 @@
<a href="{{ '/basics' | relative_url }}">Guides</a>
<ul class="dropdown-list">
<li><a href="{{ '/basics' | relative_url }}">Basics</a></li>
<li><a href="{{ '/migrations' | relative_url }}">Migrations</a></li>
<li><a href="{{ '/validations' | relative_url }}">Validations</a></li>
<li><a href="{{ '/associations' | relative_url }}">Associations</a></li>
<li><a href="{{ '/querying' | relative_url }}">Query Interface</a></li>
<li><a href="{{ '/hooks' | relative_url }}">Hooks</a></li>
<li><a href="{{ '/sequelize' | relative_url }}">Sequelize Adapter</a></li>
</ul>
</li>
<li class="nav-item">
Expand Down
4 changes: 4 additions & 0 deletions docs/_layouts/zh.html
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,12 @@
<a href="{{ '/zh/basics' | relative_url }}">上手指南</a>
<ul class="dropdown-list">
<li><a href="{{ '/zh/basics' | relative_url }}">基础</a></li>
<li><a href="{{ '/zh/migrations' | relative_url }}">表结构变更</a></li>
<li><a href="{{ '/zh/validations' | relative_url }}">数据校验</a></li>
<li><a href="{{ '/zh/associations' | relative_url }}">关联关系</a></li>
<li><a href="{{ '/zh/querying' | relative_url }}">查询接口</a></li>
<li><a href="{{ '/zh/hooks' | relative_url }}">钩子</a></li>
<li><a href="{{ '/zh/sequelize' | relative_url }}">Sequelize 适配器</a></li>
</ul>
</li>
<li class="nav-item">
Expand Down
2 changes: 1 addition & 1 deletion docs/assets/css/style.scss
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@
position: absolute;
top: 100%;
right: -0.5em;
min-width: 120px;
min-width: 140px;
text-align: right;
background: #f0f0f0;
border: 1px solid #e0e0e0;
Expand Down
102 changes: 72 additions & 30 deletions docs/basics.md
Original file line number Diff line number Diff line change
Expand Up @@ -72,15 +72,7 @@ When `Bone.remove({...})` is called on a Model with `deletedAt` present, Leoric

## Authoring Models

It's very easy to create Leoric models. Simply extend from the `Bone` class exported by Leoric:

```js
const { Bone } = require('leoric')

class Shop extends Bone {}
```

Suppose the `shops` table structure looks like below:
Suppose the `shops` table were created already:

```sql
CREATE TABLE shops (
Expand All @@ -90,7 +82,35 @@ CREATE TABLE shops (
);
```

Following the table schema above, you would be able to write code like this:
Simply extend from the `Bone` class exported by Leoric, have it connected to database, and you're all set:

```js
const { Bone } = require('leoric');
class Shop extends Bone {}
await connect({ host: 'localhost', models: [ Shop ]});
```

It is possible to manage schema with Leoric as well. By defining attributes when authring models, Leoric learns what the model needs and will have the schema migrated when necessary:

```js
const { Bone, Realm } = require('leoric');
const { BIGINT, STRING } = Bone.DataTypes;

// define Shop
class Shop extends Bone {
static attributes = {
id: { type: BIGINT, primaryKey: true },
name: { type: STRING },
}
}

// connecting Shop to shops table in database
const realm = new Realm({ host: 'localhost', models: [ Shop ] });
// synchronize model attributes to table
await realm.sync();
```

Now we have got the models connected to and synchronized with database, we can start querying:

```js
const shop = new Shop({ name: 'Horadric Cube' })
Expand All @@ -101,19 +121,19 @@ await Shop.create({ name: 'Horadric Cube' })

## Overriding the Naming Conventions

Most of the conventional names and keys can be overridden by corresponding methods. You can specify `static get table()` to override the default table name:
Most of the conventional names and keys can be overridden by corresponding methods. You can specify `static table` to override the default table name:

```js
class Shop extends Bone {
static get table() { return 'stores' }
static table = 'stores'
}
```

It's also possible to override the the name of the primary key by specifying `static get primaryKey()`:
It's also possible to override the the name of the primary key by specifying `static primaryKey`:

```js
class Shop extends Bone {
static get primaryKey() { return 'shopId' }
static primaryKey = 'shopId'
}
```

Expand All @@ -131,27 +151,49 @@ A lot of schema settings can be done within the `static describe()` method. We'l

## Connecting Models to Database

Models need to be connected to database before use. When you `connect()` models to database, Leoric will try to load table schema information and update model metadata accordingly, namely the `Model.schema`, `Model.attributes`, and `Model.columns` properties (the latter two are just getter properties which rely on `Model.schema`).
Models need to be connected to database before use, which can be connected in the following way:

```js
const { connect } = require('leoric')
const Realm = require('leoric');
const realm = new Realm({
dialect: 'mysql',
host: 'localhost',
models: '/path/to/models',
});
await realm.sync();
```

async function() {
// connect models to the database
await connect({
host: 'example.com',
port: 3306,
user: 'john',
password: 'doe',
db: 'tmall',
models: [Shop]
})

// connect models by passing the path of the containing directory
await connect({ ...opts, path: '/path/to/models' })
})
`realm.sync()` not only connects models to database, but also tries to synchronize `Model.attributes` in each model back to database structure automatically to make sure consistency between each other. If your application data changes a log, this practice is not recommended.

Intead, it is recommended only connecting to database but not to synchronize to it. Please use the [migration]({ '/migrations' | relative_url }) feature to change database structure.

```js
const Realm = require('leoric');
const realm = new Realm(...);
await realm.connect();
```

For those who started using Leoric since v0.x, we can still `connect()` to database directly.


```js
const { connect } = require('leoric');

await connect({
host: 'example.com',
port: 3306,
user: 'john',
password: 'doe',
db: 'tmall',
models: [Shop]
});

// or
await connect({ ...opts, path: '/path/to/models' });
```

If developing web applications with Egg framework, it's highly recommended using [egg-orm](https://github.com/eggjs/egg-orm) plugin.

## Reading and Writing Data

With the models defined and connected, developers can,
Expand Down
5 changes: 5 additions & 0 deletions docs/hooks.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
layout: en
---

## Hooks
12 changes: 9 additions & 3 deletions docs/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -231,7 +231,9 @@ GROUP BY genre
<tr>
<td>
{% highlight js %}
Post.find({ id: TagMap.select('targetId').where({ tagId: 1 }) })
Post.find({
id: TagMap.select('targetId').where({ tagId: 1 }),
})
{% endhighlight %}
</td>
<td>
Expand Down Expand Up @@ -300,5 +302,9 @@ LEFT JOIN tags
For detailed informations, please check out following guides accordingly:

1. [Basics]({{ '/basics' | relative_url }})
2. [Associations]({{ '/associations' | relative_url }})
3. [Query Interfaces]({{ '/querying' | relative_url }})
2. [Migrations]({{ '/migrations' | relative_url }})
3. [Validations]({{ '/validations' | relative_url }})
4. [Associations]({{ '/associations' | relative_url }})
5. [Query Interfaces]({{ '/querying' | relative_url }})
6. [Hooks]({{ '/hooks' | relative_url }})
7. [Sequelize Adapter]({{ '/sequelize' | relative_url }})
5 changes: 5 additions & 0 deletions docs/migrations.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
layout: en
---

## Migrations
33 changes: 33 additions & 0 deletions docs/sequelize.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
---
layout: en
title: Sequelize Adapter
---

To ease the transition work from sequelize to leoric, a sequelize adapter is available once the `sequelize` switch is on:

```js
const Realm = require('leoric');
const realm = new Realm({
sequelize: true, // turn on sequelize adapter
host: 'localhost',
});
await realm.sync();
```

When sequelize adapter is active, the model API will behave similarly with the actual [Sequelize Model](https://sequelize.org/master/class/lib/model.js~Model.html). See the content below for detail.

## CRUD: Reading and Writing Data

### Dirty Check

## Migrations

## Validations

## Hooks

## Associations

## Querying

### Overriding Conditions
5 changes: 5 additions & 0 deletions docs/validations.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
layout: en
---

## Validations
2 changes: 1 addition & 1 deletion docs/zh/associations.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ layout: zh
title: 关联关系
---

本文涵盖 Leoric 的关联关系特性。在阅读本文后,你将知晓
本文涵盖 Leoric 的关联关系特性。在阅读本文后,你将了解如下内容

- 如何定义数据模型间的关联关系;
- 如何理解关联关系的各种类型。
Expand Down
Loading

0 comments on commit 0207011

Please sign in to comment.