diff options
| author | syuilo <syuilotan@yahoo.co.jp> | 2019-04-14 20:38:55 +0900 |
|---|---|---|
| committer | syuilo <syuilotan@yahoo.co.jp> | 2019-04-14 20:38:55 +0900 |
| commit | d66e4b7ff97d512e2a2523815e2eef170456b37f (patch) | |
| tree | 59ae1a102d88b5c2c2236b734ea4a584b4f9ba46 /CONTRIBUTING.md | |
| parent | 10.100.0 (diff) | |
| parent | 11.0.0 (diff) | |
| download | misskey-d66e4b7ff97d512e2a2523815e2eef170456b37f.tar.gz misskey-d66e4b7ff97d512e2a2523815e2eef170456b37f.tar.bz2 misskey-d66e4b7ff97d512e2a2523815e2eef170456b37f.zip | |
Merge branch 'develop'
Diffstat (limited to 'CONTRIBUTING.md')
| -rw-r--r-- | CONTRIBUTING.md | 92 |
1 files changed, 92 insertions, 0 deletions
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index c1ad1f8041..6825225e0e 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -75,3 +75,95 @@ src ... Source code test ... Test code ``` + +## Notes +### placeholder +SQLをクエリビルダで組み立てる際、使用するプレースホルダは重複してはならない +例えば +``` ts +query.andWhere(new Brackets(qb => { + for (const type of ps.fileType) { + qb.orWhere(`:type = ANY(note.attachedFileTypes)`, { type: type }); + } +})); +``` +と書くと、ループ中で`type`というプレースホルダが複数回使われてしまいおかしくなる +だから次のようにする必要がある +```ts +query.andWhere(new Brackets(qb => { + for (const type of ps.fileType) { + const i = ps.fileType.indexOf(type); + qb.orWhere(`:type${i} = ANY(note.attachedFileTypes)`, { [`type${i}`]: type }); + } +})); +``` + +### `null` in SQL +SQLを発行する際、パラメータが`null`になる可能性のある場合はSQL文を出し分けなければならない +例えば +``` ts +query.where('file.folderId = :folderId', { folderId: ps.folderId }); +``` +という処理で、`ps.folderId`が`null`だと結果的に`file.folderId = null`のようなクエリが発行されてしまい、これは正しいSQLではないので期待した結果が得られない +だから次のようにする必要がある +``` ts +if (ps.folderId) { + query.where('file.folderId = :folderId', { folderId: ps.folderId }); +} else { + query.where('file.folderId IS NULL'); +} +``` + +### `[]` in SQL +SQLを発行する際、`IN`のパラメータが`[]`(空の配列)になる可能性のある場合はSQL文を出し分けなければならない +例えば +``` ts +const users = await Users.find({ + id: In(userIds) +}); +``` +という処理で、`userIds`が`[]`だと結果的に`user.id IN ()`のようなクエリが発行されてしまい、これは正しいSQLではないので期待した結果が得られない +だから次のようにする必要がある +``` ts +const users = userIds.length > 0 ? await Users.find({ + id: In(userIds) +}) : []; +``` + +### 配列のインデックス in SQL +SQLでは配列のインデックスは**1始まり**。 +`[a, b, c]`の `a`にアクセスしたいなら`[0]`ではなく`[1]`と書く + +### `undefined`にご用心 +MongoDBの時とは違い、findOneでレコードを取得する時に対象レコードが存在しない場合 **`undefined`** が返ってくるので注意。 +MongoDBは`null`で返してきてたので、その感覚で`if (x === null)`とか書くとバグる。代わりに`if (x == null)`と書いてください + +### 簡素な`undefined`チェック +データベースからレコードを取得するときに、プログラムの流れ的に(ほぼ)絶対`undefined`にはならない場合でも、`undefined`チェックしないとTypeScriptに怒られます。 +でもいちいち複数行を費やして、発生するはずのない`undefined`をチェックするのも面倒なので、`ensure`というユーティリティ関数を用意しています。 +例えば、 +``` ts +const user = await Users.findOne(userId); +// この時点で user の型は User | undefined +if (user == null) { + throw 'missing user'; +} +// この時点で user の型は User +``` +という処理を`ensure`を使うと +``` ts +const user = await Users.findOne(userId).then(ensure); +// この時点で user の型は User +``` +という風に書けます。 +もちろん`ensure`内部でエラーを握りつぶすようなことはしておらず、万が一`undefined`だった場合はPromiseがRejectされ後続の処理は実行されません。 +``` ts +const user = await Users.findOne(userId).then(ensure); +// 万が一 Users.findOne の結果が undefined だったら、ensure でエラーが発生するので +// この行に到達することは無い +// なので、.then(ensure) は +// if (user == null) { +// throw 'missing user'; +// } +// の糖衣構文のような扱いです +``` |