開発者ブログ
チュートリアル(データモデル編) » 03.ディスクリプタの書き方

03.ディスクリプタの書き方

Last modified by masaru-yokoyama on 2013/07/19, 14:41

hifiveのデータモデルにおける「ディスクリプタ」とは、データモデルの名前、このデータモデルに属する各データアイテムがどのようなプロパティを持っているか、またそのプロパティにはどのような型・制約があるか、などを記述したものです。
データベースにおけるスキーマ定義と似たようなものです。

データモデルを作成する時には、このディスクリプタを指定する必要があります。

なお、ディスクリプタの詳細な仕様は「リファレンス(仕様詳細) » ディスクリプタ」をご覧ください。

ディスクリプタの基本的な書き方

ディスクリプタは、オブジェクトの形で定義します(以降このオブジェクトを「ディスクリプタオブジェクト」と呼びます)。
データモデル生成時は、このオブジェクトを引数として渡します。

1つのディスクリプタオブジェクトには、1つのデータモデルについての定義を記述できます。

ディスクリプタオブジェクトは以下のように記述します。

var descriptor = {
    name: 'SampleDataModel',       // データモデルの名前(必須)
   schema: {...}                  // データアイテムのプロパティ定義(スキーマオブジェクト、必須)
};

// 記述したディスクリプタオブジェクトを基にデータモデルを作成
var model = sample.dataManager.createModel(descriptor);

このデータモデルに属するデータアイテムのプロパティ定義は、スキーマオブジェクト(上記schemaプロパティ)に記述します。

データアイテムのプロパティ定義(スキーマ)の基本的な書き方

このデータモデルに属する各データアイテムがどのようなプロパティを持つかは、スキーマオブジェクトで定義します。
スキーマオブジェクトは、先の例の通り、ディスクリプタオブジェクトのschemaプロパティにセットします。

スキーマオブジェクトには、データモデルに定義するプロパティとその定義を以下のように記述します。

schema: {
    プロパティ名1: {
        性質1-1: 値1-1,
        性質1-2: 値1-2,
        ...
    },
    プロパティ名2: {
        性質2-1: 値2-1,
        ...
    }
    ...
}

例:

schema: {
   // データアイテムを識別するためのID
   id: { id: true },  //id:trueの意味については後述

   // 名前
   name: null,

   // アドレス
   address: null
}

スキーマのIDプロパティ指定

hifiveのデータモデルでは、データベースにおける主キー列のように、各データアイテムのいずれか1つのプロパティが各インスタンスを識別できる(異なる値を持つ)必要があります。
この指定を行うのが、スキーマ定義における「id: true」の指定です。

スキーマオブジェクトには、{id: true}が指定されているプロパティが必ず1つだけ必要です
id:true指定したプロパティが、このデータモデルが持つデータアイテムを識別するためのIDプロパティとなります。
このプロパティの値は、必ずインスタンスごとに異なっていなければいけません。

その他の性質の記述

各プロパティには、性質を記述できます。nullを指定した場合は、一切の制約がないとみなされます。
詳細はリファレンス(仕様詳細) » ディスクリプタを参照してください。

type指定

プロパティに格納できる「型」を文字列で指定することができます。省略した場合はany(型制限無し)です。
型には「文字列」「製数値」「真偽値」などを指定できます。
参照:指定可能な型の一覧

typeが設定されているプロパティには、設定された型以外の値を代入することはできません。

例外として、数値型(integerまたはnumber)の型指定がされたプロパティには、数値に変換可能な文字列を代入することができます。
文字列を代入した場合、自動的に数値型に変換されてデータアイテムに格納されます。
これは、ビュー(<input>タグ等)から値を取得し、それをデータアイテムに格納する際のキャストを不要にするための対応です。

型指定の例:

var productSchema = {
   // 商品ID
   id: {id:true},

   // 商品名
   name: {
        type: 'string'
    },

   // 単価
   unitPrice: {
        type: 'integer'
    },

   // 数量
   amount: {
        type: 'integer'
    }
};

型指定を行った場合の挙動例:

var model = manager.createModel({
    name: 'ProductModel',
    schema: productSchema        // 上で記述したスキーマオブジェクト
});

var item = model.create({
    id: '001',
    name: 'ボールペン',
    unitPrice: 100,
    amount: 5000
});

// 型指定と異なる値はsetできない
item.set('amount', 'abc');       // エラーになる
    

typeの配列指定

あるプロパティを、特定の型を要素とする配列であると宣言できます。
配列指定するには、"string[]", "any[]"のように、型名の後ろに「[]」を付け加えます。

typeで配列指定すると、当該プロパティ(下の例でのlistプロパティ)にはDataItemインスタンス生成時に自動的にObservableArrayインスタンスがセットされます。このインスタンスを変更することはできません。
DataItemのset()で配列をセットしようとすると、配列そのものではなく、中身がシャローコピーされます

このObservableArrayの各要素を操作したい場合は、get(), set()メソッドを使用してください。添え字によるアクセスはできません。
var descriptor = {
    name: '',
    schema: {
        id: {
            id: true
        },
        list: {
            type: 'any[]'
        }
    }
};

var model = manager.createModel(descriptor);

var item = model.create({
    id: '001'
});

var obsAry = item.get('list');   // [] 初期値は空ObservableArray

// 配列をset
var array = ['a', 'b', 'c'];
item.set('list', array);

item.get('list');            // ['a', 'b', 'c'] のObservableArray

item.get('list') !== array;  // true, インスタンスは別

item.get('list') === obsAry; // true, 値を変更してもデータアイテムが持つObservableArrayインスタンスは変わらない

item.get('list').push('d');

item.get('list');  // ['a', 'b', 'c', 'd'] のObservableArray
DataItemインスタンスが持つObservableArrayは、relatedItemというプロパティを持ちます(ver.1.1.3以降)。
このプロパティには、自身を所有するDataItemインスタンスへの参照がセットされています。
従って、たとえばObservableArrayのイベントハンドラ内でDataItemへの参照が必要な場合は、
ハンドラ内で this.relatedItem のようにして自身を所有するDataItemインスタンスを参照できます。

depend

dependは同一データモデル内のプロパティに依存する値(計算値)を定義したいときに指定します。
depend指定されたプロパティには値をセットすることはできません(defaultValueも設定できません)。

depend指定では、「どのプロパティに依存するか」と「このプロパティの値を計算する関数」を指定します。
依存するプロパティの値が変更されると、自動的に関数が呼ばれ、このプロパティの値としてセットされます。

計算された値は、次に依存プロパティが変更されるまで自動的にキャッシュされます。
(item.get('dependProperty')のように値を取得するときは、関数は呼ばれません。)

スキーマ記述と動作例:

var productSchema = {
   // 商品ID
   id: {id:true},

   // 商品名
   name: {
        type: 'string'
    },

   // 単価
   unitPrice: {
        type: 'integer'
    },

   // 数量
   amount: {
        type: 'integer'
    },

   // 単価×数量
   totalPrice: {
        type: 'integer',
        depend: {
            on: ['unitPrice', 'amount'], // 同一データモデル内の、依存するプロパティを記述
           calc: function(ev){
               // onに指定されたいずれか1つ以上のプロパティが更新されたときにこの関数が実行されます。
               // 引数(ev)はチェンジイベントオブジェクト
               // thisはデータアイテムインスタンス

               return this.get('unitPrice') * this.get('amount');
            }
        }
    },

   // メッセージ:"(商品)は(単価×数量)円分あります"
   message: {
        type: 'string',
        depend: {
           on: ['name', 'totalPrice'],  // depend指定されている項目をさらに依存先に指定できる
          calc: function(ev) {
              return this.get('name') + 'は' + this.get('totalPrice') + '円分あります';
           }
        }
    }
};

// データモデルの作成
var model = manager.createModel({
    name: 'ProductModel',
    schema: productSchema
});

// アイテムの作成
var item = model.create({
    id: '001',
    name: 'ノート'
});

item.set({
    unitPrice: 120,
    amount: 1000
});

item.get('totalPrice');  // 1200000
item.get('message');       // "ノートは120000円分あります"

次の章では、データアイテムの更新を監視する方法について説明します。

次のステップ ⇒ データアイテムの更新とイベント


Copyright (C) 2012-2017 NS Solutions Corporation, All Rights Reserved.