Parse - Cloud Code - Getting Started
What is Cloud Code?
Parseのビジョンは、モバイルアプリを開発するデベロッパーから、サーバーの取り扱いをなくすことです。複雑なアプリケーションの場合は、ときとしてモバイルデバイス上で実行できないロジックが必要になります。Cloud Codeはこのような課題を解消します。
Cloud Codeの使い方は簡単です。なぜなら、アプリの開発で利用してきたJavaScript SDKをそのまま利用できるからです。モバイルデバイス上で動作するのか、Parse Cloud上で動作するのかという違いだけです。Cloud Codeはアップデートすると、モバイル環境へすぐに反映できるので、アプリケーションのリリースを待つ必要がなくなります。これにより、アプリケーションの更新が簡単になり、新機能も素早く追加できようになるでしょう。
あなたがモバイル開発に熟知しているとしても、Cloud Codeの理解しやすさ、簡単さを実感してもらえることでしょう。
Getting Started
開発用のコンピュータにParseコマンドラインツールをインストールしましょう。これにより、Parse Cloud上のコードを管理できるようになります。
Installing or Updating the Command Line Tool (Mac/Linux)
Mac OSやLinux/Unix環境であれば次のコマンドでインストールできます。
curl -s https://www.parse.com/downloads/cloud_code/installer.sh | sudo /bin/bash
上記のコマンドを実行すると/usr/local/bin/parseが作成されるので、"parse"コマンドを利用できるようになります。その際、余計なファイルは生成されませんので、アンインストールしたい場合は/usr/local/bin/parseを削除するだけです。また、既にインストール済みのコマンドをアップデートするこもできます。
Installing the Command Line Tool (Windows)
Window用のコマンドラインツールはこちらにあります。zipファイルをダウンロード、解凍した後、ParseConsole.exeをダブルクリックするとpowershellセッションが起動します。ParseConsoleが起動したらWin + R と“parse”コマンドでpowershellセッションを開始します。*1
Setting Up Cloud Code
次のステップは、クラウド上で実行するコードを格納するためにディレクトリを作成します。parse newコマンドはディレクトリをセットアップし、作成対象のアプリケーションの選択を要求します。
$ parse new MyCloudCode Email: ninja@gmail.com Password: 1:MyApp Select an App: 1 $ cd MyCloudCode
Parseのログインに必要なEメールアドレスとパスワードを入力します。OAuth経由でサインアップしてパスワードをセットしたことがない場合、アカウントの設定をその場で編集する必要があります。以上でカレントディレクトリ上にMyCloudCodeディレクトリが作成されます。ディレクトリの中にはいくつかのファイルが自動生成されています。
-config/ global.json -cloud/ main.js -public/ index.html
configディレクトリは、JSON形式の設定ファイルが格納されています。たいていは、このファイルを編集することはありません。cloudディレクトリにはCloud Codeが格納されており、publicディレクトリにはParse上でホストする静的コンテンツが格納されています。cloudディレクトリのmain.jsにCloud Codeファンクションを記述します。現時点では、正しくファイルが生成されていることを確認しておいてください。もし、ソース管理を行うなら、これらのファイルはすべてチェックインすることができます。
A Simple Function
古代からの伝統に従い、クラウド上で動作する最もシンプルなファンクションを実行してみます。cloud/main.jsを開くと、文字列を返すサンプルを確認できます。
Parse.Cloud.define("hello", function(request, response) { response.success("Hello world!"); });
このコードをあなたのマシンからParse Cloudにデプロイするには、次のコマンドを実行します。
$ parse deploy
デプロイが完了したら、次のコマンドを実行してみましょう。
curl -X POST \ -H "X-Parse-Application-Id: Your-Parse-Application-Id" \ -H "X-Parse-REST-API-Key: Your-Parse-Rest-Api-Key" \ -H "Content-Type: application/json" \ -d '{}' \ https://api.parse.com/1/functions/hello
次のようなレスポンスを確認できるでしょう。
{ "result": "Hello world!" }
おめでとうございます。デプロイが完了し、Cloud Codeも正しく動作しています。
開発のサイクルを確認する良い機会ですので、"Hello world!"を他の文字列に変更しデプロイと実行を試してみてください。異なる結果が返ることを確認しましょう。JavaScript SDKのすべてをCloud Code上で利用できるので、できることはたくさんあります。以降、いくつかのサンプルを見ていくことにします。
*1:powershellは使ったことがないです。。
AndroidでParse入門 - まとめ的な -
これはなにか
流行のParseの勉強をしたかったので、本家のAndroidドキュメントを読みながら勉強した記録です。
Android Developer Guide | Parse
翻訳?
英語はできないので雰囲気で訳してます。*1
まとめ
AndroidでParse入門 - Objects - - Murayama blog.
AndroidでParse入門 - Queries - - Murayama blog.
AndroidでParse入門 - Subclasses - - Murayama blog.
AndroidでParse入門 - Files - - Murayama blog.
AndroidでParse入門 - Analytics - - Murayama blog.
AndroidでParse入門 - Users - - Murayama blog.
AndroidでParse入門 - Roles - - Murayama blog.
AndroidでParse入門 - Facebook Users - - Murayama blog.
AndroidでParse入門 - Twitter Users - - Murayama blog.
AndroidでParse入門 - Cloud Functions - - Murayama blog.
AndroidでParse入門 - GeoPoints - - Murayama blog.
AndroidでParse入門 - User Interface - - Murayama blog.
*1:間違えてたらごめんなさい
AndroidでParse入門 - Security -
元ネタ
こちらを参考にSecurityについてまとめます。
https://parse.com/docs/android_guide#security-recommendations
前回の記事はこちら。
AndroidでParse入門 - Handling Errors - - Murayama blog.
Security
Parseはアプリケーションの構築において可能な限りデータアクセスを制限することを強く推奨しています。具体的にはアプリケーションの初期化時に、Anonymous Userの作成やCurrent UserへのデフォルトACLの適用を定義することを推奨しています。また、データを不正アクセスから守るために、個々のオブジェクトにPublicな書き込み制限(および、読み込み制限)を明示的に設定するようにします。
アプリケーションのスタートアップ処理の中で次のように実装します。
ParseUser.enableAutomaticUser(); ParseACL defaultACL = new ParseACL(); // Optionally enable public read access while disabling public write access. // defaultACL.setPublicReadAccess(true); ParseACL.setDefaultACL(defaultACL, true);
データへのセキュアなアクセスを保つことを念頭において、あなたとユーザの両方を保護するアプリケーションを構築してください。
AndroidでParse入門 - Handling Errors -
元ネタ
こちらを参考にHandling Errorsについてまとめます。
https://parse.com/docs/android_guide#errors
前回の記事はこちら。
AndroidでParse入門 - User Interface - - Murayama blog.
Handling Errors
ParseObjectのsave()、delete()、get()といった多くのメソッドは、削除、編集すべきデータが存在しない場合や、ネットワーク通信の不具合などによって、リクエストを処理できなければParseExceptionをスローします。そのような場合、必要に応じてアプリケーション内でこれらの例外をキャッチし例外処理を施す必要があります。
詳細についてはAndroid APIを参照してください。
AndroidでParse入門 - User Interface -
元ネタ
こちらを参考にUser Interfaceについてまとめます。
https://parse.com/docs/android_guide#ui
User Interface
アプリケーションのユーザはAndroidのUIコンポーネントと対話します。ParseはParse上のデータを効率よく扱うための共通的なUIウィジェットのサブクラスを提供しています。
ParseQueryAdapter
Parseはコレクションデータを表示するためにAdapterの実装クラスを提供しています。静的なオブジェクト配列を使うベーシックなListAdapterを使う代わりに、ParseQueryAdapterクラスを使えば抽象的なレイヤーが提供されます。その結果、AdapterView(たとえばListView、GridView)を使って、Parseクラスのデータを簡単に表示できるようになります。
Activity上でデータを表示するためのParseQueryAdapterの使い方は、onCreateメソッドで次のように実装します。
- ParseQueryAdapterを生成します。
- 必要に応じてカスタマイズします(データの問い合わせ、ビューの変更などの詳細については、後のセクションを参照してください)
- setAdapter()メソッドによってAdapterViewにAdapterをセットします。
WindowにAdapterViewがアタッチされると、ParseQueryAdapterは自動的にデータの先頭部分をフェッチします。このサブクラスは次に示すコードを簡略化します。
- タップで次のページを読み込むページネーション
- 行内のリモートイメージの表示やダウンロードの設定
- Parseオブジェクト配列の自動読み込み管理
- データライフサイクルにおける主要なイベントからのコールバック
次のコードは、ListViewにデータを表示するためのシンプルなParseQueryAdapterのセットアップです。わずかな設定で機能的なListViewが実装できます。
// Inside an Activity public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); // Uses a layout with a ListView (id: "listview"), which uses our Adapter. setContentView(R.layout.main); ParseQueryAdapter<ParseObject> adapter = new ParseQueryAdapter<ParseObject>(this, "Instrument"); adapter.setTextKey("name"); adapter.setImageKey("photo"); ListView listView = (ListView) findViewById(R.id.listview); listView.setAdapter(adapter); }
このビューはInstrumentsリストのnameを表示します。ここでは記述していないコードに注目してください。連続したページのフェッチロジックを記述していませんし、配列データの管理ロジックも記述していません。UIウィジェットに表示するイメージをバックグラウンドでダウンロードするコードもないですし、次のページをロードするタッチイベントの処理も記述していません。
ParseQueryAdapterは、データの加工や表示方法、フェッチ時の前処理、後処理をカスタマイズできます。以降の節では、ParseQueryAdapterを使ってあなたが何をできるのかを解説します。ニーズに合わせるために、どのように微調整すれば良いかを見ていきましょう。
Customizing the Query
ParseQueryAdapterのコンストラクタは、ContextとParseのクラス名を引数に取ります。これにより、クラスに属するすべてのParseObjectがフェッチされ、createdAtタイムスタンプ順に表示されます。
Parseは、この振る舞いを変更できるようにArrayAdapterの機能から設計しています。ParseQueryAdapterは、Adapterによって表示されるオブジェクト配列を設定するのではなく、自分で定義したParseQueryを返すQueryFactoryクラスを引数に受け取ります。QueryFactoryインスタンスをコンストラクタで受け取ることで、Adapterはクエリの結果を使用し、オブジェクトをフェッチして表示するようになります。
次のコードは、punkとmetalで4名以上メンバーがいるバンドをレコードの売上順で表示するためのParseQueryAdapterのセットアップです。
ParseQueryAdapter<ParseObject> adapter = new ParseQueryAdapter<ParseObject>(this, new ParseQueryAdapter.QueryFactory<ParseObject>() { public ParseQuery<ParseObject> create() { // Here we can configure a ParseQuery to our heart's desire. ParseQuery query = new ParseQuery("Band"); query.whereContainedIn("genre", Arrays.asList({ "Punk", "Metal" })); query.whereGreaterThanOrEqualTo("memberCount", 4); query.orderByDescending("albumsSoldCount"); return query; } });
Customizing the Rows
AdapterView内の個々ビューのデフォルトレイアウトは、ParseImageViewとTextViewによるシンプルなLinearLayoutです。ParseQueryAdapterに対してsetTextKey(String) を呼び出すと、指定したキーがParseObjectの表示項目となり、TextViewに表示されます。同様に、setImageKey(String)を呼び出すと、指定したキーがParseObjectの表示項目となり、ImageViewに表示されます。
行をカスタマイズする一つの方法は、getItemView(ParseObject, View, ViewGroup) やgetNextPageView(View, ViewGroup)をオーバーライドし、スーパークラスの適切なメソッドを呼び出す方法です。独自のレイアウトをスーパークラスの実装に提供する場合、getItemView(ParseObject, View, ViewGroup) とgetNextPageView(View, ViewGroup) は、textKeyがセットされているならTextView (id: android.R.id.text1)、imageKeyがセットされているならParseImageView (id: android.R.id.icon)を期待します。*1
独自のレイアウトをinflateして設定し、TextViewとParseImageView、さらに"description"TextView(id: R.id.description)を追加する場合、次のようになります。
@Override public View getItemView(ParseObject object, View v, ViewGroup parent) { if (v == null) { v = View.inflate(getContext(), R.layout.adapter_item, null); } // Take advantage of ParseQueryAdapter's getItemView logic for // populating the main TextView/ImageView. // The IDs in your custom layout must match what ParseQueryAdapter expects // if it will be populating a TextView or ImageView for you. super.getItemView(object, v, parent); // Do additional configuration before returning the View. TextView descriptionView = (TextView) v.findViewById(R.id.description); descriptionView.setText(object.getString("description")); return v; }
行をカスタマイズするもう一つの方法は、ParseQueryAdapterのメソッドをオーバーライドし、スーパークラスの実装を完全に無視する方法です。ParseObjectに定義されたcolorを個々のItem Viewに適用するシンプルな例は次のようになります。
@Override public View getItemView(ParseObject object, View v, ViewGroup parent) { if (v == null) { v = View.inflate(getContext(), R.layout.adapter_item, null); } v.setBackgroundColor(object.getInt("color")); return v; } @Override public View getNextPageView(View v, ViewGroup parent) { if (v == null) { // R.layout.adapter_next_page contains an ImageView with a custom graphic // and a TextView. v = View.inflate(getContext(), R.layout.adapter_next_page, null); } TextView textView = (TextView) v.findViewById(R.id.nextPageTextViewId); textView.setText("Loaded " + getCount() + " rows. Get more!"); return v; }
Loading Remote Images in Rows
ParseQueryAdapterは、簡単にリモートイメージを表示することができます。setImageKey(String)を呼び出せば、ParseFileを保持したParseObjectのキー名を通じて、Parseからイメージをフェッチし対象行のParseImageViewにロードします。
イメージは非同期でダウンロードされるので、ParseImageViewはバックグラウンドで更新されます。ユーザのスクロールにより、Adapterによって行がリサイクルされると、ParseObjectが割り当てられ、イメージがフェッチされて表示されます。
画像のフェッチが完了するまでプレースホルダイメージを定義することもできます。ParseQueryAdapterのsetPlaceholder(Drawable) を呼び出すと、指定したDrawableがフォールバックイメージとして描画されます。
Lifecycle Methods
カスタムロジックを適用するために、Adapterに2つのデータライフサイクルフックを用意しています。一つは、データのクエリの前処理であり、もう一つはクエリからフェッチされたオブジェクトがロードされたときの後処理です。これらのメソッドは、ロードされたUIの切り替えなどに有効です。OnQueryLoadListenerはsetOnQueryLoadListenerによってセットします。onLoading() とonLoaded(List, Exception) を実装する必要があります。
Pagination
ページネーションは、テーブルからリストの1ページ目だけを取得します。ページに含むオブジェクトの件数は、setObjectsPerPage(int)を呼び出すことで指定できます。
クエリはページネーションによって自動的に調整されます。AdapterViewの最終行にページネーション行が表示されるので、ユーザは次のページを読み込むことができます。
ページネーションはデフォルトで有効となっています。無効にしたい場合はsetPaginationEnabled(false)を呼び出してください。ページネーションを無効にすると、ParseQueryAdapterはデフォルトで最大100件の結果を読み込みます。
Auto-loading of Data
ParseQueryAdapterを設定したAdapterViewがWindowにアタッチされると、先頭のページをフェッチする際にParseQueryAdapterのloadObjects()メソッドが呼び出されます。この挙動を無効にしたい場合(データの読み込みを遅延させたり、カスタムロジックを実行させたりしたい場合)、setAutoload(false)を呼び出してください。その場合、loadObjects()は手動で呼び出すようにします。
*1:変な言い回しですみません、後のコード見た方が良いです。
AndroidでParse入門 - GeoPoints -
元ネタ
こちらを参考にGeoPointsについてまとめます。
https://parse.com/docs/android_guide#geo
前回の記事はこちら。
AndroidでParse入門 - Cloud Functions - - Murayama blog.
GeoPoints
Parseのオブジェクトは緯度・経度といった位置情報をサポートしています。ParseObjectにParseGeoPointを追加することで、指定した位置情報の近くにあるオブジェクトを問い合わせることが可能となります。この仕組みを使う事で、あるユーザの近くにいる人を見つけたり、ある場所の近くにいるユーザを見つけたりといったことが簡単にできるようになります。
ParseGeoPoint
オブジェクトに位置情報を関連づけるにはParseGeoPointを作ります。緯度40.0、経度-30.0を指定するなら次のようになります。
ParseGeoPoint point = new ParseGeoPoint(40.0, -30.0);
この位置情報は、オブジェクトのフィールドに保存できます。
placeObject.put("location", point);
Geo Queries
位置情報を持つオブジェクトを多数用意できたなら、ある地点から最も近いオブジェクトを見つけることができます。これにはParseQueryのwhereNearメソッドを制約として使います。10件の場所のリストを取得する場合は次のようになります。
ParseGeoPoint userLocation = (ParseGeoPoint) userObject.get("location"); ParseQuery<ParseObject> query = ParseQuery.getQuery("PlaceObject"); query.whereNear("location", userLocation); query.setLimit(10); query.findInBackground(new FindCallback<ParseObject>() { ... });
useLocationの地点から、距離の近い順でリストオブジェクトが返却されます。ただし、orderByAscending()/orderByDescending()を指定した場合は、距離の順序よりも優先されます。
距離を使って結果を制限したい場合は、whereWithinKilometers、whereWithinMiles、whereWithinRadiansメソッドを使用してください。
特定のエリアに含まれるオブジェクトを問い合わせることもできます。ある矩形の範囲内に含まれるオブジェクトを探したいなら、ParseQueryのwhereWithinGeoBoxメソッドを使います。
ParseGeoPoint southwestOfSF = new ParseGeoPoint(37.708813, -122.526398); ParseGeoPoint northeastOfSF = new ParseGeoPoint(37.822802, -122.373962); ParseQuery<ParseObject> query = ParseQuery.getQuery("PizzaPlaceObject"); query.whereWithinGeoBox("location", southwestOfSF, northeastOfSF); query.findInBackground(new FindCallback<ParseObject>() { ... });
Caveats
いくつか注意事項があります。
- 個々のParseObjectクラスには、ParseGeoPointオブジェクトを一つのキーでしか保持できません。
- 位置情報は、範囲の上限を超えてはいけません。緯度は-90.0から90.0、経度は180.0から180.0を超えてはいけません。範囲外の値を設定するとエラーとなります。
AndroidでParse入門 - Cloud Functions -
元ネタ
こちらを参考にCloud Functionsについてまとめます。
https://parse.com/docs/android_guide#cloudfunctions
前回の記事はこちら。
AndroidでParse入門 - Twitter Users - - Murayama blog.
Cloud Functions
Cloud Functionsは、ParseCloudによってAndroidから呼び出すことができます。たとえば、helloという名前のCloud Functionを呼び出すなら次のようになります。
ParseCloud.callFunctionInBackground("hello", new HashMap<String, Object>(), new FunctionCallback<String>() { void done(String result, ParseException e) { if (e == null) { // result is "Hello world!" } } });
Cloud Functionsについて詳しく知りたいならCloud Code Guideを参照してください。