Leoric
- +Leoric is an object-relational mapping for Node.js, which is heavily influenced by Active Record of Ruby on Rails. See the documentation for detail.
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 connected to the database, the columns of the tables are mapped as attributes, the associations are setup, feel free to start querying.
Usage
// define model class Post extends Bone { - static describe() { + static initialize() { this.belongsTo('author', { Model: 'User' }) this.hasMany('comments') } @@ -167,7 +168,7 @@Related Projects
diff --git a/docs/api/module-lib_bone.html b/docs/api/module-lib_bone.html deleted file mode 100644 index 25ceafa4..00000000 --- a/docs/api/module-lib_bone.html +++ /dev/null @@ -1,328 +0,0 @@ - - - - - -
lib/bone
- - - - - - - -The Bone to extend models from. This module consists of helper methods like capitalize
, and the class Bone
.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
Methods
- - - -(inner) copyValues(values) → {Object}
- - - - - -copy values for validation
--
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
Parameters:
- - -Name | - - -Type | - - - - - -Description | -
---|---|---|
values |
-
-
-
-
-
-Object
-
-
-
- |
-
-
-
-
-
- - - - | -
Returns:
- - - --
-
- - Type: - -
-
-
-
Object
- - -
-
copied values
-- - - - - - - - - \ No newline at end of file diff --git a/docs/api/module-src_bone.html b/docs/api/module-src_bone.html new file mode 100644 index 00000000..f2783d52 --- /dev/null +++ b/docs/api/module-src_bone.html @@ -0,0 +1,328 @@ + + + + + +
src/bone
+ + + + + + + +The Bone to extend models from. This module consists of helper methods like capitalize
, and the class Bone
.
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Methods
+ + + +(inner) copyValues(values) → {Object}
+ + + + + +copy values for validation
+-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Parameters:
+ + +Name | + + +Type | + + + + + +Description | +
---|---|---|
values |
+
+
+
+
+
+Object
+
+
+
+ |
+
+
+
+
+
+ + + + | +
Returns:
+ + + +-
+
- + Type: + +
-
+
+
Object
+ + +
+
copied values
++ + + + + + + + + \ No newline at end of file diff --git a/docs/api/module-lib_expr.html b/docs/api/module-src_expr.html similarity index 60% rename from docs/api/module-lib_expr.html rename to docs/api/module-src_expr.html index 61c2c872..8ab49dff 100644 --- a/docs/api/module-lib_expr.html +++ b/docs/api/module-src_expr.html @@ -3,7 +3,7 @@ -
lib/expr
+src/expr
@@ -1585,7 +1585,7 @@Parameters:
diff --git a/docs/api/module-lib_spell.html b/docs/api/module-src_spell.html similarity index 53% rename from docs/api/module-lib_spell.html rename to docs/api/module-src_spell.html index 10475ad0..c4ffb4b2 100644 --- a/docs/api/module-lib_spell.html +++ b/docs/api/module-src_spell.html @@ -3,7 +3,7 @@ -
lib/spell
+src/spell
@@ -306,14 +306,14 @@Example:
-(inner) isOperatorCondition(condition) → {boolean}
+(inner) formatValueSet(spell, obj, strict) → {Object}
Check if object condition is an operator condition, such as { $gte: 100, $lt: 200 }
.
Translate key-value pairs of attributes into key-value pairs of columns. Get ready for the SET part when generating SQL.
Parameters:
+Parameters:
condition
spell
Spell
+
+
+
+ obj
Parameters:
+key-value pairs of attributes
+ +strict
boolean
+
+
+
+ check attribute exist or not
Returns:
boolean
+Object
Parameters:
Might be Model.aliasName, Model.table, or other names given by users
+Might be Model.tableAlias, Model.table, or other names given by users
Example:
-(inner) parseLogicalObjectCondition(name, value)
+(inner) parseSet(spell, obj)
+Translate key-value pairs of attributes into key-value pairs of columns. Get ready for the SET part when generating SQL.
+Parameters:
name
spell
string
+Spell
@@ -1318,699 +1390,25 @@ Parameters:
logical operators, such as $or
, $and
value
Object
-|
-
-Array.<Object>
-
-
-
- logical operands
Example:
- -{ $or: { title: 'Leah', content: 'Diablo' } }
-{
- $or: [
- { title: 'Leah' },
- { content: 'Diablo' },
- ],
-}
-{
- title: {
- $or: [
- 'Leah',
- 'Diablo',
- ]
- }
-}
-{
- title: {
- $or: [
- 'Leah',
- {
- $like: '%jjj'
- },
- ]
- }
-}
-{
- title: {
- $not: [
- 'Leah',
- 'jss'
- ]
- }
-}
-
-(inner) parseObjectConditions(conditions)
- - - - - -parse conditions in MongoDB style, which is quite polular in ORMs for JavaScript. See module:lib/spell~OPERATOR_MAP
for supported $op
s.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
Parameters:
- - -Name | - - -Type | - - - - - -Description | -|
---|---|---|---|
conditions |
+ obj |
Object
+|
-
-
- |
-
-
-
-
-
- - - - | -
Example:
- -{ foo: null }
-{ foo: { $gt: new Date(2012, 4, 15) } }
-{ foo: { $between: [1, 10] } }
-
-(inner) parseObjectValue(value) → {Object}
- - - - - -Parse object values as literal or subquery
--
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
Parameters:
- - -Name | - - -Type | - - - - - -Description | -
---|---|---|
value |
-
-
-
-
-
-*
-
-
-
- |
-
-
-
-
-
- - - - | -
Returns:
- - - --
-
- - Type: - -
-
-
-
Object
- - -
-
(inner) parseOperatorCondition(name, condition) → {Object}
- - - - - -parse operator condition into expression ast
--
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
Parameters:
- - -Name | - - -Type | - - - - - -Description | -
---|---|---|
name |
-
-
-
-
-
-string
-
-
-
- |
-
-
-
-
-
- - - - | -
condition |
-
-
-
-
-
-Object
-
-
-
- |
-
-
-
-
-
- - - - | -
Returns:
- - - --
-
- - Type: - -
-
-
-
Object
- - -
-
Example:
- -parseOperatorCondition('id', { $gt: 0, $lt: 999999 });
-// => { type: 'op', name: 'and', args: [ ... ]}
-
-(inner) parseSet(spell, obj)
- - - - - -Translate key-value pairs of attributes into key-value pairs of columns. Get ready for the SET part when generating SQL.
--
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
Parameters:
- - -Name | - - -Type | - - - - - -Description | -
---|---|---|
spell |
-
-
-
-
-
-Spell
-
-
-
- |
-
-
-
-
-
- - - - | -
obj |
-
-
-
-
-
-Object
+Array
@@ -2144,7 +1542,7 @@ (inner) diff --git a/docs/basics.md b/docs/basics.md index 36a453ce..14367289 100644 --- a/docs/basics.md +++ b/docs/basics.md @@ -137,17 +137,27 @@ class Shop extends Bone { } ``` -You can rename the attribute names too. By default, these names are transformed from column names by calling `static renameAttribute(oldName, newName)` in the `static describe()` method. +We can rename the attribute names too. By default, these names are transformed from column names by converting them into camel case. If the names don't match, we can specify the column names manually in `static attributes`, such as: ```js class Shop extends Bone { - static describe() { + static attributes = { + deletedAt: { type: DATE, columnName: 'removed_at' }, + } +} +``` + +We can also rename the attribute in the `static initialize()` method, which gets called after models are loaded. + +```js +class Shop extends Bone { + static initialize() { this.renameAttribute('removedAt', 'deletedAt') } } ``` -A lot of schema settings can be done within the `static describe()` method. We'll get to that later. +A lot of schema settings can be done within the `static initialize()` method. We'll get to that later. ## Connecting Models to Database diff --git a/docs/index.md b/docs/index.md index f030f775..3d15565e 100644 --- a/docs/index.md +++ b/docs/index.md @@ -10,7 +10,7 @@ const { Bone, connect } = require('leoric') // define model class Post extends Bone { - static describe() { + static initialize() { this.belongsTo('author', { Model: 'User' }) this.hasMany('comments') } diff --git a/docs/querying.md b/docs/querying.md index 530e83c2..2a59f6af 100644 --- a/docs/querying.md +++ b/docs/querying.md @@ -437,7 +437,7 @@ Predefined associations can be found by examining `Model.relations`, which is ge ```js class Post extends Bone { - static describe() { + static initialize() { this.hasMany('comments') this.belongsTo('author', { foreignKey: 'authorId', Model: 'User' }) } diff --git a/docs/zh/associations.md b/docs/zh/associations.md index 21fb8488..1525f262 100644 --- a/docs/zh/associations.md +++ b/docs/zh/associations.md @@ -47,7 +47,7 @@ Leoric 支持四种关联关系: ```js class Item extends Bone { - static describe() { + static initialize() { this.belongsTo('shop') } } @@ -57,7 +57,7 @@ Leoric 会把关联关系的名称 `shop` 转为驼峰、首字母大写,再 ```js class Item extends Bone { - static describe() { + static initialize() { this.belongsTo('shop', { className: 'Seller' }) } } @@ -73,7 +73,7 @@ class Item extends Bone { ```js class Item extends Bone { - static describe() { + static initialize() { this.belongsTo('shop', { foreignKey: 'sellerId' }) } } @@ -89,7 +89,7 @@ class Item extends Bone { ```js class Shop extends Bone { - static describe() { + static initialize() { this.hasMany('items') } } @@ -103,7 +103,7 @@ Leoric 寻找对应数据模型的方式都是差不多的。首先将关联关 ```js class Shop extends Bone { - static describe() { + static initialize() { this.hasMany('items', { className: 'Commodity' }) } } @@ -113,7 +113,7 @@ class Shop extends Bone { ```js class Shop extends Bone { - static describe() { + static initialize() { this.hasMany('items', { foreignKey: 'sellerId' }) } } @@ -137,7 +137,7 @@ class Shop extends Bone { ```js class Shop extends Bone { - static describe() { + static initialize() { // the extra where is needed if you fancy this generic tag system this.hasMany('tagMaps', { foreignKey: 'targetId', where: { targetType: 0 } }) this.hasMany('tags', { through: 'tagMaps' }) @@ -149,7 +149,7 @@ class Shop extends Bone { ```js class Tag extends Bone { - static describe() { + static initialize() { this.hasMany('shopTagMaps', { className: 'TagMap', where: { targetType: 0 } }) this.hasMany('shops', { through: 'shopTagMaps' }) } @@ -160,7 +160,7 @@ class Tag extends Bone { ```diff class Tag extends Bone { - static describe() { + static initialize() { this.hasMany('shopTagMaps', { className: 'TagMap', where: { targetType: 0 } }) this.hasMany('shops', { through: 'shopTagMaps' }) + this.hasMany('itemTagMaps', { className: 'TagMap', where: { targetType: 1 } }) @@ -185,7 +185,7 @@ class Tag extends Bone { ```js class User extends Bone { - static describe() { + static initialize() { this.hasOne('shop', { foreignKey: 'ownerId' }) } } @@ -195,7 +195,7 @@ class User extends Bone { ```js class Shop extends Bone { - static describe() { + static initialize() { this.belongsTo('owner', { className: 'User' }) } } diff --git a/docs/zh/basics.md b/docs/zh/basics.md index 3303644e..85488993 100644 --- a/docs/zh/basics.md +++ b/docs/zh/basics.md @@ -120,11 +120,11 @@ await Shop.create({ name: 'Horadric Cube' }) ## 覆盖命名约定 -绝大部分命名约定都有对应的覆盖方法,我们可以使用 `static get table()` 覆盖表名: +绝大部分命名约定都有对应的覆盖方法,我们可以使用 `static table` 覆盖表名: ```js class Shop extends Bone { - static get table() { return 'stores' } + static table = 'stores' } ``` @@ -132,21 +132,31 @@ class Shop extends Bone { ```js class Shop extends Bone { - static get primaryKey() { return 'shopId' } + static primaryKey = 'shopId' } } ``` -也可以重命名属性名,在 `static describe()` 方法中调用 `static renameAttribute(oldName, newName)` 即可: +以及使用 `static attributes` 自定义数据模型属性对应的字段名: ```js class Shop extends Bone { - static describe() { + static attributes = { + deletedAt: { type: DATE, columnName: 'removed_at' }, + } +} +``` + +如果数据模型的属性信息不在模型中直接维护,也可以等数据模型信息从数据库加载后,在 `static initialize()` 方法中重命名属性名: + +```js +class Shop extends Bone { + static initialize() { this.renameAttribute('removedAt', 'deletedAt') } } ``` -`static describe()` 方法中可配置的项目有很多。我们之后再详细讨论。 +`static initialize()` 方法中可配置的项目有很多。我们之后再详细讨论。 ## 连接数据模型和数据库 diff --git a/docs/zh/index.md b/docs/zh/index.md index 89c432bf..b57f1682 100644 --- a/docs/zh/index.md +++ b/docs/zh/index.md @@ -10,7 +10,7 @@ const { Bone, connect } = require('leoric') // 基于 Bone 定义模型,映射关系表 class Post extends Bone { - static describe() { + static initialize() { this.belongsTo('author', { Model: 'User' }) this.hasMany('comments') } diff --git a/docs/zh/querying.md b/docs/zh/querying.md index 71dda15c..776db4af 100644 --- a/docs/zh/querying.md +++ b/docs/zh/querying.md @@ -431,7 +431,7 @@ Leoric 提供两种构建 JOIN 查询的方式: ```js class Post extends Bone { - static describe() { + static initialize() { this.hasMany('comments') this.belongsTo('author', { foreignKey: 'authorId', Model: 'User' }) } diff --git a/src/bone.js b/src/bone.js index 27d17e82..73a49afb 100644 --- a/src/bone.js +++ b/src/bone.js @@ -820,7 +820,7 @@ class Bone { * restore rows * @param {Object} conditions query conditions * @param {Object?} opts query options - * @returns + * @returns {Spell} */ static restore(conditions, opts = {}) { const { deletedAt } = this.timestamps; diff --git a/src/spell.js b/src/spell.js index ead5c192..eae17e04 100644 --- a/src/spell.js +++ b/src/spell.js @@ -65,7 +65,7 @@ function parseSelect(spell, ...names) { * @param {Spell} spell * @param {Object} obj - key-value pairs of attributes * @param {boolean} strict - check attribute exist or not - * @returns + * @returns {Object} */ function formatValueSet(spell, obj, strict = true) { const { Model, silent = false, command } = spell; |