node package manager
Painless code sharing. npm Orgs help your team discover, share, and reuse code. Create a free org »

activehashie-validation

activehashie-validation.js - The ActiveModel like validation for ActiveHashie

npm npm license npm download total npm download by month

Dependency Status devDependency Status Travis Build Status AppVeyor Build Status codecov.io Codacy Badge

Rails等のマスターデータをJavaScript/TypeScriptでチェック可能にするツールです。

使用方法

rails_app/db/seeds.rbにてデータをテーブルごとにymlファイルから読み込む仕組みになっているとします。

下記のようにchecker/にチェック用の内容を書いて、checker/フォルダでahevコマンドを実行すると、エラー内容が記載されたreport.htmlが生成されます。

なおこの内容はexamples/の下にあります。

rails_app/db/seeds/items.yml:

data1:
  id: 1
  name: item1
  type: a
  item_group_id: 1
data2:
  id: 2
  name: item2
  type: a
  item_group_id: 1
data3:
  id: 3
  name: item3
  type: b
  item_group_id: 2
data4:
  id: 4
  name: item3
  type: c
  item_group_id: 2

rails_app/db/seeds/item_groups.yml:

data1:
  id: 1
  name: group1
data2:
  id: 2
  name: group2
data3:
  id: 3
  name: group2

checker/models/application_record.ts:

import {
    ActiveHashRecord,
    ActiveHashRecordBase,
    ActiveYaml,
} from "activehashie";
 
const rootPath = "../rails_app/db/seeds";
 
export class ApplicationRecord<Record extends ActiveHashRecord> extends ActiveYaml<Record> {
    constructor(
        name: string,
        recordClass: new (source: ActiveHashRecordBase) => Record,
        indexColumns?: Array<keyof (Record)>,
    ) {
        super(name, recordClass, {rootPath, indexColumns});
    }
}
 
// displayNameメソッドを定義しておくと、エラー表示の時にそのレコードを表すものとして使われます。
(<any> ActiveHashRecord.prototype).displayName = function () {
    return this.name;
};

checker/models/item.ts:

import {ActiveHashRecord} from "activehashie";
import {validate} from "activehashie-validation";
import {ApplicationRecord} from "./application_record";
import {ItemGroup, ItemGroupRecord} from "./item_group";
 
export class ItemRecord extends ActiveHashRecord {
    name: string;
    type: "a" | "b";
    item_group_id: number;
    get itemGroup(): ItemGroupRecord | undefined { return this.belongsTo(ItemGroup); }
 
    displayName() {
        const itemGroup = this.itemGroup;
        return `${itemGroup ? itemGroup.name : ""} - ${this.name} [${this.type}]`;
    }
}
 
export const Item = new ApplicationRecord("Item", ItemRecord);
 
validate(Item, ({validates, validate}) => {
    validates("name", "presence", true);
    validates("name", "uniqueness", true);
    validates("type", "presence", true);
    validate((errors, model) => {
        const ids = model.where().not({type: ["a", "b"]}).pluck("id");
        if (ids.length) {
            errors.push({column: "type", ids, message: "typeは'a', 'b'のいずれかであるべきです"});
        }
    });
    validates("itemGroup", "presenceBelongsTo", true); // 参照先の存在をチェックします
});

checker/models/item_group.ts:

import {ActiveHashRecord} from "activehashie";
import {validate} from "activehashie-validation";
import {ApplicationRecord} from "./application_record";
import {Item} from "./item";
 
export class ItemGroupRecord extends ActiveHashRecord {
    name: string;
    get items() { return this.hasMany(Item); }
}
 
export const ItemGroup = new ApplicationRecord("ItemGroup", ItemGroupRecord);
 
validate(ItemGroup, ({validates}) => {
    validates("name", "presence", true);
    validates("name", "uniqueness", true);
});

checker/spec/length.ts:

import {validate} from "activehashie-validation";
import "../models/item";
import {ItemGroup} from "../models/item_group";
 
validate(ItemGroup, ({validate}) => {
    validate((errors, model) => {
        if (model.length < 10) {
            errors.push({message: "ItemGroupは10個以上必要です"});
        }
    });
});

See also

License

This is released under MIT License.