53
28

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.

TypeORMのmigrationで作成されるテーブル名をカスタマイズする

Posted at

はじめに

TypeORM、素晴らしいんですが、作成したモデルを元にmigrationを掛けると残念なことになります。

例えば、
モデル名 UserHoge → 作成されるテーブル名 user_hoge
プロパティ名 firstName → 作成されるカラム名 firstName

なんでテーブルはスネークケース、カラムはキャメルケースで連結なんだ :sob:

こうあってほしい

テーブル・カラム命名規約

Railsの規約がしっくり来るので、それ風にしたい。

  • テーブル名: モデルのスネークケース複数形 user_hoges
  • カラム名: スネークケース first_name

コード

とは言っても、rubyと違って(Type|Java)Scriptの変数命名規約がキャメルケースなので、
コード上はキャメルケースで書きたい

  • モデル名: キャメルケース単数 UserHoge
  • プロパティ名: キャメルケース firstName

うまい方法はないかと探した結果、上記は2通りの方法で実現できそうです。

[方法1] 個別でテーブル・カラム名を定義する

@Entityデコレーター、@Columnデコレーター共に、個別で名前を指定することができます。

@Entity('users') // これ!
export class User extends BaseEntity {
  @PrimaryGeneratedColumn()
  public id: number

  @Column({ name: 'first_name' }) // これ!
  public firstName: string = ''
}

これを元にmigrationを作成すると、指定した名前に応じたSQL文が発行されます。

これで、
「コード上はモデル名:User カラム名: firstName
「DB上はテーブル名:users カラム名: first_name

を実現できるわけですが、すべてのテーブル・カラムに個別に名前を付けていたのでは
ヌケモレが発生したとき大変なことになりますし、何より面倒くさいです。

[方法2] 名前付けルールを設定する

ormconfigに独自の名前付けルールを設定する事で、個別に名前を設定しなくても
自動的にORM⇔DB間でいい感じに変換してくれるようになります。

1. 設定ファイルを作成

ここではconfig/TypeOrmNamingStrategy.jsという名前で作ります。

やっていることは、公式が用意してるDefaultNamingStrategyを継承して、
ルールを書き換えただけです。(念の為、デフォルトのルールはこちら)

自分はモデルから作るテーブルの他に、多対多のリレーションの中間テーブルの名前等も変えてます。
他にもOverrideしたい場合は、適宜。


var DefaultNamingStrategy = require('typeorm').DefaultNamingStrategy
var snakeCase = require('typeorm/util/StringUtils').snakeCase
var pluralize = require('pluralize')

module.exports = class TypeOrmNamingStrategy extends DefaultNamingStrategy {
  tableName(className, customName) {
    return customName || pluralize(snakeCase(className))
  }

  columnName(propertyName, customName, embeddedPrefixes) {
    return snakeCase(embeddedPrefixes.join('_')) + (customName || snakeCase(propertyName))
  }

  relationName(propertyName) {
    return snakeCase(propertyName)
  }

  joinColumnName(relationName, referencedColumnName) {
    return snakeCase(pluralize.singular(relationName) + '_' + referencedColumnName)
  }

  joinTableName(firstTableName, secondTableName, firstPropertyName, secondPropertyName) {
    return snakeCase(firstTableName + '_' + secondTableName)
  }

  joinTableColumnName(tableName, propertyName, columnName) {
    return snakeCase(pluralize.singular(tableName) + '_' + (columnName || propertyName))
  }

  classTableInheritanceParentColumnName(parentTableName, parentTableIdPropertyName) {
    return snakeCase(pluralize.singular(parentTableName) + '_' + parentTableIdPropertyName)
  }
}

2. ormconfigを編集する

先程作ったカスタム名前付けルールのクラスを読み込むようにします。
設定内でクラスをインスタンス化しているため、ormconfig.jsonでは駄目です。
json拡張子を使っている人は、ormconfig.jsに変更してください。

ormconfig.js
const TypeOrmNamingStrategy = require('./src/configs/TypeOrmNamingStrategy.js') // これ!

module.exports = {
  // 色々独自の設定
  type: 'postgres',
  host: process.env.DB_HOSTNAME,
  port: 5432,
  username: process.env.DB_USERNAME,
  password: process.env.DB_PASSWORD,
  ...
  namingStrategy: new TypeOrmNamingStrategy() // これ!!
}

3. いつも通りmigrationを当てる

カスタムルールに基づいた命名規則でmigrationが作られるようになります。

53
28
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
53
28

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?