2
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

[adonis.js] Modelにgetterを追加するときにasyncを使う方法

Last updated at Posted at 2019-06-05

出力するjsonにテーブルにない項目を追加したいとき、Modelにgetterを追加することになります。(参考)

しかし、getter内でasyncを使いたい時(例えば別のテーブルから値を参照したい時)、上記の方法では出来ないのでhookを使うことになります。

hookを使った方法のサンプルがなかったので記事として残しておきます。

前提

  • adonis.js 4.1

サンプルコード

Modelはすでに作ってあるとします。

次にHookを作成します。

adonis make:hook PostHook

Hookは /app/Models/Hooks に作られます。

次に Hook を編集します。

/app/Models/Hooks/PostHook.js
'use strict'

const Code = use('App/Models/Code') // コードマスタ

const PostHook = exports = module.exports = {}

PostHook.computedFields = async (modelInstance) => {
  if (Array.isArray(modelInstance)) {
    modelInstance = await Promise.all(computedFields.map(bindCodeNames))
  } else {
    modelInstance = await computedFields(modelInstance)
  }
}

async function computedFields(model) {
  // ここで追加したいFieldを代入していく
  model.status_name = await Code.get('status', model.status)

  return model
}

最後にModel側に追記します。

/app/Models/Post
'use strict'
const Model = use('Model')

class Post extends Model {
  static boot() {
    super.boot()

    // 以下3つを追加
    this.addHook('afterFind', 'PostHook.computedFields')
    this.addHook('afterFetch', 'PostHook.computedFields')
    this.addHook('afterPaginate', 'PostHook.computedFields')
  }
}

動作サンプル

start/routes.js
const Post = use('App/Models/Post')

Route.get('post/:id', ({params, response}) => {
  const post = Post.findOrFail(params.id)
  return response.send(post) // { ..., status: 1, status_name: '公開' }
})

追記 2019.06.11

この方法でgetterを追加した場合、更新時( save() 時)、追加したgetterの名前のカラムが無いとSQLでエラーを吐かれます。そのため、更新時に要素を削除するという処理を入れる必要が出てきます。

以下、処理の例です。

/app/Models/Hooks/PostHook.js
// 追加
PostHook.removeComputedFields = (modelInstance) => {
  modelInstance = removeComputedFields(modelInstance)
}

function removeComputedFields(model) {
  delete model.$attributes.status_name

  return model
}
/app/Models/Post.js
class Post extends Model {
  static boot() {
    super.boot()

    this.addHook('afterFind', 'PostHook.computedFields')
    this.addHook('afterFetch', 'PostHook.computedFields')
    this.addHook('afterPaginate', 'PostHook.computedFields')

    // 追加
    this.addHook('beforeUpdate', 'PostHook.removeComputedFields')
  }
}

deleteで無理やりプロパティを消してるので、なんか他にいい方法無いのかなと思うのですが調べても出てこない感じでした……。


adonis.jsはJavascript(Node.js)製のWebフレームワーク。laravelに似ており全てをjavascriptで書くことができます。
日本でも広まれー!

2
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?