Skip to content

Commit

Permalink
Docs: a syntax table
Browse files Browse the repository at this point in the history
  • Loading branch information
cyjake committed Dec 17, 2017
1 parent 3e5e8ad commit 4d05744
Show file tree
Hide file tree
Showing 4 changed files with 236 additions and 32 deletions.
67 changes: 66 additions & 1 deletion Readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,69 @@
[![NPM Version](http://img.shields.io/npm/v/leoric.svg?style=flat)](https://www.npmjs.com/package/leoric)
[![Build Status](https://travis-ci.org/dotnil/leoric.svg)](https://travis-ci.org/dotnil/leoric)

Leoric is an object-relational mapping for Node.js, which is heavily influenced by Active Record. See the [documentation](http://cyj.me/leoric) for detail.
Leoric is an object-relational mapping for Node.js, which is heavily influenced by Active Record of Ruby on Rails. See the [documentation](http://cyj.me/leoric) for detail.

## Requirements

Currently, Leoric only supports MySQL (and variants such as MariaDB) database.

## Usage

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

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

// define model
class Post extends Bone {
static describe() {
this.belongsTo('author', { Model: 'User' })
this.hasMany('comments')
}
}

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

// CRUD
await Post.create({ title: 'King Leoric' })
const post = await Post.findOne({ title: 'King Leoric' })
post.title = 'Skeleton King'
await post.save()

// or UPDATE directly
await Post.update({ title: 'Skeleton King' }, { title: 'King Leoric' })

// find with associations
const postWithComments = await Post.findOne({ title: 'King Leoric' }).with('comments')
console.log(post.comments) // => [ Comment { id, content }, ... ]
}
```

## Syntax Table

| JavaScript | SQL |
|-----------------------------------------|----------------------------------------------------|
| `Post.create({ title: 'King Leoric' })` | `INSERT INTO posts (title) VALUES ('King Leoric')` |
| `Post.all` | `SELECT * FROM posts` |
| `Post.find({ title: 'King Leoric' })` | `SELECT * FROM posts WHERE title = 'King Leoric'` |
| `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` |
| `Post.limit(20)` | `SELECT * FROM posts LIMIT 0, 20` |
| `Post.update({ id: 42 }, { title: 'Skeleton King' })` | `UPDATE posts SET title = 'Skeleton King' WHERE id = 42` |
| `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) 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, 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.
4 changes: 2 additions & 2 deletions docs/Gemfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -200,7 +200,7 @@ GEM
mini_portile2 (~> 2.3.0)
octokit (4.7.0)
sawyer (~> 0.8.0, >= 0.5.3)
pathutil (0.16.0)
pathutil (0.16.1)
forwardable-extended (~> 2.6)
public_suffix (2.0.5)
rb-fsevent (0.10.2)
Expand All @@ -211,7 +211,7 @@ GEM
i18n
rubyzip (1.2.1)
safe_yaml (1.0.4)
sass (3.5.3)
sass (3.5.4)
sass-listen (~> 4.0.0)
sass-listen (4.0.0)
rb-fsevent (~> 0.9, >= 0.9.4)
Expand Down
23 changes: 23 additions & 0 deletions docs/assets/css/style.scss
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,29 @@
}
}

.markdown-body .syntax-table {
width: 100%;
font-size: 90%;

th, td {
width: 60%;
}

.highlight {
margin: 0;
background: transparent;
}

.highlight pre {
padding: 4px 0;
background: transparent;
}

code br {
display: block;
}
}

@media(min-width: 1000px) {
.belongs-to-erd,
.has-many-erd,
Expand Down
174 changes: 145 additions & 29 deletions docs/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,39 +34,155 @@ async function() {
}
```

Leoric can be used as pure query builder too. Take the `Post` model above for another example:

```js
## Syntax Table

<table class="syntax-table">
<thead>
<tr>
<th>JavaScript</th>
<th>SQL</th>
</tr>
</thead>
<tbody>
<tr>
<td>
{% highlight js %}
Post.find({ id: [1, 2, 3] })
// SELECT * FROM articles WHERE id IN (1, 2, 3);

{% endhighlight %}
</td>
<td>
{% highlight sql %}
SELECT * FROM posts WHERE id IN (1, 2, 3);
{% endhighlight %}
</td>
</tr>
<tr>
<td>
{% highlight js %}
Post.select('id, title').where('title like ?', '%Leoric%')
// SELECT id, title FROM articles WHERE title LIKE '%Leoric%';

Post.select('count(id) as count').group('authorId').having('count > 0').order('count', 'desc')
// SELECT count(id) AS count FROM articles GROUP BY author_id HAVING count > 0 ORDER BY count DESC;

{% endhighlight %}
</td>
<td>
{% highlight sql %}
SELECT id, title FROM posts WHERE title LIKE '%Leoric%';
{% endhighlight %}
</td>
</tr>
<tr>
<td>
{% highlight js %}
Post.where('title like ? || authorId = ?', '%Leoric%', 42)
{% endhighlight %}
</td>
<td>
{% highlight sql %}
SELECT * FROM posts WHERE title LIKE '%leoric%' OR author_id = 42;
{% endhighlight %}
</td>
</tr>
<tr>
<td>
{% highlight js %}
Post
.select('count(id) as count')
.group('authorId')
.having('count > 0')
.order('count', 'desc')
{% endhighlight %}
</td>
<td>
{% highlight sql %}
SELECT count(id) AS count, author_id
FROM posts
GROUP BY author_id
HAVING count > 0
ORDER BY count DESC;
{% endhighlight %}
</td>
</tr>
<tr>
<td>
{% highlight js %}
Book.average('price').group('genre').having('average > 50')
{% endhighlight %}
</td>
<td>
{% highlight sql %}
SELECT AVG('price') AS average, genre
FROM books
GROUP BY genre
HAVING average > 50;
{% endhighlight %}
</td>
</tr>
<tr>
<td>
{% highlight js %}
Post.find({ id: TagMap.select('targetId').where({ tagId: 1 }) })
// SELECT * FROM articles WHERE id IN (SELECT target_id FROM tag_maps WHERE tag_id = 1);
```

Both predefined joins and arbitrary joins are supported:

```js
Post.find({}).with('author', 'comments')
// SELECT * FROM articles AS posts
// LEFT JOIN users ON users.id = posts.author_id LEFT JOIN comments ON comments.post_id = articles.id;

Post.find({}).join(Attachment, 'attachments.postId = posts.id')
// SELECT * FROM articles AS posts LEFT JOIN attachments ON attachments.post_id = posts.id;

Post.find({})
.join(TagMap, 'tagMaps.targetId = posts.id and tagMaps.targetType = ?', 0)
{% endhighlight %}
</td>
<td>
{% highlight sql %}
SELECT *
FROM posts
WHERE id
IN (SELECT target_id FROM tag_maps WHERE tag_id = 1);
{% endhighlight %}
</td>
</tr>
<tr>
<td>
{% highlight js %}
Post.include('author', 'comments')
{% endhighlight %}
</td>
<td>
{% highlight sql %}
SELECT *
FROM posts AS posts
LEFT JOIN users ON users.id = posts.author_id
LEFT JOIN comments ON comments.post_id = posts.id;
{% endhighlight %}
</td>
</tr>
<tr>
<td>
{% highlight js %}
Post.join(Attachment, 'attachments.postId = posts.id')
{% endhighlight %}
</td>
<td>
{% highlight sql %}
SELECT *
FROM posts AS posts
LEFT JOIN attachments ON attachments.post_id = posts.id;
{% endhighlight %}
</td>
</tr>
<tr>
<td>
{% highlight js %}
Post
.join(TagMap,
'tagMaps.targetId = posts.id and tagMaps.targetType = 0')
.join(Tag, 'targetMaps.tagId = tags.id')
// SELECT * FROM articles AS posts
// LEFT JOIN tag_maps AS tagMaps ON tagMaps.target_id = posts.id AND tag_maps.target_type = 0
// LEFT JOIN tags ON tagMaps.tag_id = tags.id;
```
{% endhighlight %}
</td>
<td>
{% highlight sql %}
SELECT *
FROM posts AS posts
LEFT JOIN tag_maps AS tagMaps
ON tagMaps.target_id = posts.id AND tag_maps.target_type = 0
LEFT JOIN tags
ON tagMaps.tag_id = tags.id;
{% endhighlight %}
</td>
</tr>
</tbody>
</table>

## Guides

For detailed informations, please check out following guides accordingly:

Expand Down

0 comments on commit 4d05744

Please sign in to comment.