[MBaaS][Parse] Cloud CodeのトリガFunctionでバックエンド機能を拡張する [其の2]

2014.07.14

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

ずいぶん間が空きましたが、こんにちは。よく訓練されたXPERIA信者の小室です。 XPERIA Zがとある事情から無限タップ状態に陥って天に召されてしまったので、Z2を買いました。 これで私の端末乗り換え履歴は、X10, NX, Z, Z2となりました。

Cloud Code

cloud_code

ここ最近、Parseが採用されるアプリケーションが増えてきました。 有名なところだと、LINEの「Whoscall」にParseが採用されているようです。これを機に少しずつ日本でもメジャーになれば良いな、と思ってますがどうでしょう。

前回に引き続き、ParseのCloud Codeの続きです。

トリガFunction

Parseには、Cloud Codeを利用してバックエンド機能をカスタマイズして拡張することが出来ることは、前回ご紹介した通りです。Cloud Codeで定義できるFunctionについては、大きく2つの種類があります。

  1. ユーザー任意のタイミングで実行することが出来る。カスタムしたAPIの口を用意することの出来る。カスタムFunction
  2. Parseが自動的に適切なタイミングで実行してくれる。トリガFunction

今回はトリガFunctionの方について大きく紹介します。 トリガFunctionとは、データストアの操作をフックしてParseが自動的に実行してくれるFunctionです。データストアへの操作の直前や直後のタイミングで勝手に実行されます。

動作イメージ

Trigger_Function

beforeSave()

指定されたクラスのオブジェクトを新たに作成される場合、存在するオブジェクトを更新する場合に、処理実行前に実行されます。 入力パラメータのチェックやオブジェクトの事前状態のチェック、他のオブジェクトデータの取得などに利用できます。

定義

Parse.Cloud.beforeSave("Class名", function(request, response) {
});

対応したクラスに対して保存処理が実行されると、保存処理前にこのFunctionが呼ばれます。

パラメータ名
request Parse.Cloud.BeforeSaveRequest 主に「保存前のパラメータ情報」や「保存を実行したユーザー情報」などを持つオブジェクト
response Parse.Cloud.BeforeSaveResponse 事前処理完了後、成功(success)か失敗(error)のいずれかを実行するためのオブジェクト

サンプルコード

例えば入力されるパラメータのチェック

// ゲームが保存される前に事前チェック
Parse.Cloud.beforeSave("GameMaster", function(request, response) {
  // 保存対象のパラメータを取得
  var params = request.object;

  // 作成者情報がないとエラー
  var createdBy = params.get("createdBy");
  if(createdBy != null) {
    response.success();
  } else {
    response.error();
  }
});

これで入力されるパラメータのチェックなどが出来ます。 今回は単なる有無のチェックですが、入力される日付のチェックや作成するユーザーの妥当性のチェックなどが出来ますね。

例えば上限値以上の値の丸め込み

Parse.Cloud.beforeSave("ScoreBoard", function(request, responset) {
  // パラメータを取得
  var params = request.object;

  // 点数を取得
  var score = params.get("score");

  // 1000点を超えていたら、上限値999に設定する
  if(score >= 1000) {
    request.object.set("score", 999);
  } 
  response.success();
});

こちらは上限値を超えた値が入ってきたらエラーにするのではなく、上限値に丸め込んでパラメータをセットし直すサンプルです。 特にerror()になる場合はありませんが、こんなことも可能です。

afterSave()

指定されたクラスのオブジェクトを新たに作成される場合、存在するオブジェクトを更新する場合に、処理実行後に実行されます。 オブジェクトの作成、変更に紐付いて、別のオブジェクトを操作したい場合などに利用できます

定義

Parse.Cloud.afterSave("Class名", function(request) {
});

対応したクラスに対して保存処理が実行されると、保存処理後にこのFunctionが呼ばれます。beforeSave()との異なり、response が存在しないことに注意します。

パラメータ名
request Parse.Cloud.AfterSaveRequest すでに保存が完了した値や保存を実行したユーザー情報などを含んだオブジェクトです。

カートに保存されたアイテムをPush通知で自分に送る

Parse.Cloud.afterSave("Cart", function(request) {

	// 保存されたオブジェクト
	var saved = request.object;

	// カートに追加されたアイテム情報(名前と個数)
	var itemName = saved.get("itemName");
	var count = saved.get("count");
	// 保存を実行したユーザー情報
	var owner = saved.user;

	if(count > 0)  {
		var message = itemName + "が" + count + "個追加されました"
		console.log(message);

		// ユーザー情報にマッチするInstallationを探すクエリ
		var query = new Parse.Query(Parse.Installation);
		query.equalTo("user", owner);

		// 自分自身にPush通知をする
		Parse.Push.send({
			where: query,
			data: {
					alert: message
			}
		},
		{
			success: function() {
				// Push was successful
			},
			error: function(error) {
				// Handle error
				status.error(error);
			}
		});

	}
});

こんな感じで、データ更新後の処理を記述することができます。

!!注意!!

この機能を使う時は、簡単に無限ループが作れてしまうことに充分留意して作ってください!! afterSave() の中で再度同じクラスのデータの保存処理を呼び出すと最悪無限ループします。

無限ループ

【NG】消費税を掛けて保存し直す

Parse.Cloud.afterSave("Cart", function(request){
	// 保存されたオブジェクト
	var saved = request.object;

	// 消費税を掛けて保存し直す
	var price = saved.get("price");
	if(price > 0) {
		var taxinPrice = price * 1.08;
		saved.set("price", taxinPrice);

		// 新しい値を保存し直す
		saved.save();
	}
});

これを実行すると、ひたすら1.08をかけ続けます。

beforeDelete()

指定されたクラスのオブジェクトを削除する場合に、処理実行前に実行されます。 beforeSaveと同じく入力パラメータの事前チェックなどに利用できます。

定義

Parse.Cloud.beforeDelete("Class名", function(request, response) {
});

beforeSave()とほぼ変わりません。削除処理を行う前にこのFunctionが呼ばれます。

パラメータ名
request Parse.Cloud.BeforeDeleteRequest 主に「削除対象のオブジェクト情報」や「削除を実行したユーザー情報」などを持つオブジェクト
response Parse.Cloud.BeforeDeleteResponse 事前処理完了後、成功(success)か失敗(error)のいずれかを実行するためのオブジェクト。成功を返せばそのまま削除され、失敗を返すと削除処理が中断される。

削除処理が実行される前に、削除して良いものかどうかをチェックするなどに利用できます。

削除対象のアイテムが発送済みかどうか

Parse.Cloud.beforeDelete("Cart", function(request, response) {
	// 削除対象を取得
	var target = request.object;

	// 発送済みどうか
	var shipping = target.get("shipping");
	if(shipping) {
		// すでに発送されてしまってるので消せません
		response.error();
	} else {
		//発送されてないので消せます
		response.success();
	}
});

発送済みかどうかをチェックして、アイテムが削除可能かどうかを判定します。 (カート内のアイテムのステータスに発送済みとかがあるかどうかはこの際目を瞑って頂いて・・・)

afterDelete()

指定されたクラスのオブジェクトを削除する場合に、処理実行後に実行されます。 afterSaveと同じく、処理完了後に別オブジェクトの操作などに利用できます。

定義

Parse.Cloud.afterDelete("Class名", function(request) {
});

削除処理完了後に実行されます。削除されてしまったオブジェクト情報などを扱うことが可能です。こちらもafterSave() と同じくrequestしか存在しません。

パラメータ名
request Parse.Cloud.AfterDeleteRequest すでに削除が完了したオブジェクト情報や削除を実行したユーザー情報などを含んだオブジェクトです。

これは、主に「◯◯を削除しました」などの通知などに使えそうです

まとめ

今回は、Cloud CodeのトリガFunctionについて紹介しました。紹介したようにデータの事前チェックや、データ保存をトリガにした様々な拡張を簡単に実装することができます。 これらをうまく駆使することで、かなり柔軟にバックエンドの動作を変更することが出来ることが分かりました。トリガFunctionを制するものはCloud Codeを制すと言っても過言ではないかもしれません。

今後のトピックは以下の通りです。

  • 独自のAPIを作成できるカスタムFunction
  • バックグラウンド処理を作成するジョブFunction
  • デバッグ方法, ログの監視方法

それでは皆様ごきげんよう

参照