Docs Menu
Docs Home
/ /
Atlas App Services

チュートリアル: FTXUI を使用した C++ 用 Atlas Device Sync

項目一覧

  • 学習目的
  • 前提条件
  • テンプレートを使用して開始
  • テンプレート アプリを調べる
  • アプリを開く
  • アプリをビルドする
  • アプリ構造の探索
  • アプリを実行する
  • バックエンドの確認
  • アプリケーションを変更する
  • 新しいプロパティの追加
  • モデルへのプロパティの追加
  • 優先順位を設定するために UI に要素を追加する
  • 新しいプロパティをデータベースに保存する
  • およびテストの実行
  • サブスクリプションを変更する
  • サブスクライブを更新する
  • およびテストの実行
  • まとめ
  • 次のステップ

完了までの推定時間: 30分(C++ の経験により異なります)

Atlas Device SDK for C++ を使用すると、携帯電話、テーブル、ウェアラブル、または IoT デバイス全体でデータを保存および同期できます。 This tutorial is based on the C++ Template App, named cpp.todo.flex, which illustrates the creation of a to-do list terminal GUI application built with FTXUI. このアプリケーションを使用すると、ユーザーは次のことが可能になります。

  • メールを新しいユーザー アカウントとして登録します。

  • メールとパスワードを使用してアカウントにサインインします(その後サインアウトします)。

  • 自分のタスクを表示、作成、変更、削除します。

  • ユーザーが所有者でない場合でも、すべてのタスクを表示します。

また、テンプレートアプリには、デバイスがオフラインモードになっていることをシミュレートするトグルが用意されています。 このトグルを使用すると、シミュレーターで Device Sync 機能をすばやくテストして、インターネットに接続していないユーザーをエミュレートできます。 ただし、本番アプリケーションではこのトグルを削除する可能性が高いでしょう。

このチュートリアルでは、テンプレート アプリを対象に構築を行います。 既存のItemモデルに新しいpriorityフィールドを追加し、 Flexible Sync サブスクライブを更新して、優先順位の範囲内のアイテムのみを表示します。

このチュートリアルでは、テンプレート アプリを独自のニーズに合わせて調整する方法について説明します。 テンプレート アプリの現在の構造を考慮すると、必ずしもこの変更を行う必要はありません。

このチュートリアルでは、次の方法を学習します。

  • 重大じゃない変更で C++ オブジェクト モデルを更新します。

  • Device Sync サブスクライブを更新します。

  • 同期されるデータを変更するには、サーバー上の Device Sync 構成にクエリ可能なフィールドを追加します。

Tip

ガイド付きチュートリアルに従うのではなく、独自のアプリケーションを使い始める場合は、 C++ クイック スタートを確認します。 コピー可能なコード サンプルと、Atlas App Services バックエンドを設定するために必要な重要な情報が含まれています。

  • 必要なソフトウェアがインストールされていることを確認してください。 C++ テンプレート アプリでは、次のことを前提としています。

    • CMax バージョン3 。25 以上

    • C++ 17以上

  • このチュートリアルは、テンプレート アプリから始めます。 テンプレート アプリを作成するには、 Atlas アカウント、 API キー、 App Services CLI が必要です。

    • Atlas アカウントの作成の詳細については、「 Atlas の使用開始」ドキュメントを参照してください。 このチュートリアルでは、無料階層クラスターを持つ Atlas アカウントが必要です。

    • ログインする MongoDB Cloud アカウントの Atlas API キーも必要です。 App Services CLI を使用してテンプレート アプリを作成するには、プロジェクト オーナーである必要があります。

    • App Services CLI のインストールについて詳しくは、「 App Services CLI のインストール」を参照してください。 インストール後、Atlas プロジェクトの API キーを使用して「 login 」コマンドを実行します。

このチュートリアルは、 cpp.todo.flexという名前の C++ Sync テンプレート アプリを基本にして作成されており、 デフォルトのアプリから始めて、新しい機能について説明しています。

テンプレート アプリの詳細については、「テンプレート アプリ 」を参照してください。

Atlas アカウントがまだない場合は、テンプレート アプリを配置するためにサインアップしてください。

App Services App」ガイドに記載されている手順に従い、 Create App from Templateを選択します。Real-time Sync テンプレートを選択します。これにより、Device Sync テンプレート App Services App クライアントの 1 つで使用するために事前構成された App Services App が作成されます。

テンプレート アプリを作成すると、UI に Get the Front-end Code for your Template というラベルの付いたモーダルが表示されます。このモーダルには、テンプレート アプリのクライアントコードを .zip ファイルとしてダウンロードする方法や、App Services CLI を使用してクライアントを取得する方法が表示されます。

C++ テンプレート アプリはまだ、App Services UI ではダウンロードできません。 CLIを使用するか、 Githubからリポジトリをクローンしてクライアントコードを取得します。

appservices apps createコマンドでバックエンドを設定し、C++ テンプレート アプリを作成してこのチュートリアルのベースとして使用します。

ターミナル ウィンドウで次のコマンドを実行して、「Myチュートリアル App」という名前のアプリを作成し、環境が「開発」(本番環境やQAではなく)に設定されているUS-VAリージョンに配置されます。

appservices app create \
--name MyTutorialApp \
--template cpp.todo.flex \
--deployment-model global \
--environment development

このコマンドは、 --nameフラグの値と同じ名前で現在のパスに新しいディレクトリを作成します。

Device Sync クライアントコードを含む Github リポジトリをフォークしてクローンできます。 C++ クライアント コードは https://github.com/mongodb/template-app-cpp-todo で入手できます。

このプロセスを使用してクライアントのコードを取得する場合は、クライアントで使用するテンプレート アプリを作成する必要があります。 「テンプレート アプリの作成」 の手順に従って、Atlas App Services UI、App Services CLI、または管理 API を使用して Device Sync テンプレート アプリを作成します。

1

希望する IDE でフロントエンド クライアント コードを開きます。

Githubリポジトリからクライアントをクローンした場合は、クライアント内の適切な場所にApp Services App IDを手動で挿入する必要があります。 アプリ ID を挿入する場所については、クライアントREADME.mdConfiguration手順に従ってください。

2
  1. アプリをビルドするディレクトリを作成します。 便宜上、テンプレート アプリにパッケージ化された.gitignoreは、クライアント ディレクトリ内のbuildディレクトリを無視します。 ビルド ディレクトリに移動します。

    mkdir build && cd build
  2. CSpec を使用して Search ファイルを作成します。 クライアント ディレクトリ内のbuildディレクトリから構築しているとします。

    cmake ../
  3. CSpec を使用してアプリ実行可能ファイルを構築します。 これには、依存関係をインストールし実行可能ファイルをコンパイルする際にいくつかの時間がかかります。

    cmake --build .
3

CSpec が実行可能ファイルを構築している間にプロジェクトがどのように構成されているかを調べます。

このチュートリアルではこれらのファイルを直接操作することはありませんが、C++ SDK の使用を示すコードが含まれています。

ファイル
目的
controllers/app_controller.cpp

nlohmann::jsonライブラリを使用して、 atlasConfig.jsonから値を読み取ります。 次に、これらの値を使用してrealm::Appを初期化し、アプリの 状態で保存します。 Appは、アプリケーションが App Services バックエンドと通信する方法を示します。 これにより、認証とログイン ユーザーのrealm::userオブジェクトにアクセスできます。

アプリ構成をカスタマイズする方法の詳細については、「 Atlas App Services バックエンドへの接続 」を参照してください。

このコードでは、 AuthManagerErrorManagerも設定します。 ログイン ユーザーがいるかどうかに応じて、ユーザーをLoginControllerまたはHomeControllerに送信するナビゲーション フローが含まれています。

managers/auth_manager.cpp
メール/パスワード ユーザーを登録し、ユーザーをログインまたはログアウトさせ、認証エラーが発生したときにエラー メッセージを表示するロジック。

このチュートリアルでは、次のファイルを操作します。

ファイル
目的
state/item.hpp
データベースに保存するItemオブジェクトを定義します。
state/home_controller_state.hpp
ホーム ビューでアプリの状態を管理します。
controllers/home_controller.hpp
Home ビュー コントローラーの重要な定義が含まれています。
controllers/home_controller.cpp
ホーム ビューを実装します。 これは、ログインしたユーザーがアプリを操作できるビューです。
managers/database_manager.hpp
Device Sync とデータベース操作のための重要な定義が含まれています。
managers/database_manager.cpp
アイテムの作成、Device Sync クエリ サブスクリプションの変更、Sync エラーの処理など、一部の Device Sync およびデータベース操作を実装します。
4

コードを変更しなくても、ターミナルでアプリを実行できるはずです。 アプリケーションを実行する際に、 atlasConfig.jsonへのパスを引数として渡します。

./sync_todo /path-to-file/atlasConfig.json

アプリを実行し、新しいユーザーアカウントを登録し、新しいアイテムを Todo リストに追加します。

Tip

必要に応じて、ターミナル ウィンドウを展開します。

ホーム画面の上部には、一連のボタンと、完了したタスクを非表示にするトグルが含まれています。 ターミナル ウィンドウが小さすぎると、ボタンのテキスト ラベルは表示されません。 ラベルを表示するには、ターミナル ウィンドウを大きくし、FTXUI がより大きなウィンドウに収まるようにコンテンツを再レンダリングします。

5

Atlas App Servicesにログインします。 Data Servicesタブで、 Browse Collectionsをクリックします。 データベースのリストで、 todoデータベース、 Itemコレクションを検索して展開します。 このコレクションで作成したドキュメントが表示されます。

1

すべて期待どおりに動作していることが確認できたため、変更を追加できます。 このチュートリアルでは、各Itempriorityプロパティを追加し、アイテムを優先順位でフィルタリングできます。

本番アプリでは、可能な値を制限するためにPriorityLevel列挙型を追加できます。 このチュートリアルでは、数値プロパティを使用して UI フレームワークの操作を簡素化します。

これを行うには、次の手順に従います。

  1. 希望する IDE でクライアント コードを開きます。

  2. state/ディレクトリで、 item.hppファイルを追加します。

  3. 次のプロパティをItem構造体に追加します。

    int64_t priority;
  4. 新しいpriorityプロパティをREALM_SCHEMA()に追加する。

    REALM_SCHEMA(Item, _id, isComplete, summary, owner_id, priority)

    Itemモデルは次のようになります。

    namespace realm {
    struct Item {
    realm::primary_key<realm::object_id> _id{realm::object_id::generate()};
    bool isComplete;
    std::string summary;
    std::string owner_id;
    int64_t priority;
    };
    REALM_SCHEMA(Item, _id, isComplete, summary, owner_id, priority)
    } // namespace realm
2
  1. state ディレクトリで、home_controller_state.hpp にGoします。 既存のnewTaskIsCompleteプロパティの下に新しいintプロパティを追加します。 次に、このプロパティのデフォルトの int 値を保存するためにstatic const intを追加します。

    HomeControllerState構造は次のようになります。

    struct HomeControllerState {
    static const int DEFAULT_TASK_PRIORITY = 3;
    // Used for creating a new task.
    std::string newTaskSummary;
    bool newTaskIsComplete{false};
    int newTaskPriority{DEFAULT_TASK_PRIORITY};
    ...more code here...
    };
  2. controllers ディレクトリで、home_controller.hpp にGoします。 このコントローラーは、アプリのメインビューをレンダリングします。

    string ライブラリとベクトル ライブラリをインポートします。

    #include <string>
    #include <vector>

    新しい優先順位 UI 要素のstringラベルの配列を作成します。

    std::vector<std::string> priorityLevelLabels = {
    "Severe", "High", "Medium", "Low"
    };
  3. まだ controllers ディレクトリにある場合は、home_controller.cpp にGoします。 ここで、ユーザーがアイテムの優先順位を設定できるように UI 要素を追加します。 FTXUI は、この機能に使用できる 2 つの UI 要素を提供しています( RadioboxまたはDropdown 。 このチュートリアルではDropdownを使用しますが、UI がドロップダウンをレンダリングするためにリフローする方法が望ましくない場合は、 Radioboxを使用する方が適しているかもしれません。

    この新しい UI 要素の入力をauto newTaskCompletionStatus行の後に追加します。

    auto newTaskPriorityDropdown = ftxui::Dropdown(
    &priorityLevelLabels,
    &_homeControllerState.newTaskPriority
    );

    auto saveButton関数閉じで、タスク優先順位の選択を_dbManager.addNew()関数呼び出しに渡します。

    _dbManager.addNew(
    _homeControllerState.newTaskIsComplete,
    _homeControllerState.newTaskSummary,
    _homeControllerState.newTaskPriority);

    次に、優先順位の選択をデフォルト値にリセットする行を追加します。

    _homeControllerState.newTaskPriority = HomeControllerState::DEFAULT_TASK_PRIORITY;

    アイテム行コンテナ内のインタラクティブ要素の配置を設定するauto newTaskLayoutにドロップダウン セレクターを追加します。

    auto newTaskLayout = ftxui::Container::Horizontal(
    {inputNewTaskSummary, newTaskCompletionStatus, newTaskPriorityDropdown, saveButton});

    コードのこのセクションは次のようになります。

    auto newTaskCompletionStatus = ftxui::Checkbox("Complete", &_homeControllerState.newTaskIsComplete);
    auto newTaskPriorityDropdown = ftxui::Dropdown(
    &priorityLevelLabels,
    &_homeControllerState.newTaskPriority);
    auto saveButton = ftxui::Button("Save", [this] {
    _dbManager.addNew(
    _homeControllerState.newTaskIsComplete,
    _homeControllerState.newTaskSummary,
    _homeControllerState.newTaskPriority);
    _homeControllerState.newTaskSummary = "";
    _homeControllerState.newTaskIsComplete = false;
    _homeControllerState.newTaskPriority = HomeControllerState::DEFAULT_TASK_PRIORITY;
    });
    auto newTaskLayout = ftxui::Container::Horizontal(
    {inputNewTaskSummary, newTaskCompletionStatus, newTaskPriorityDropdown, saveButton});
  4. 最後に、 home_controller.cppファイルのさらに下にあるセカンダリの UI 要素をauto itemListRendererに追加します。

    inputNewTaskSummary->Render() | ftxui::flex,
    newTaskCompletionStatus->Render() | ftxui::center,
    newTaskPriorityDropdown->Render(),
    saveButton->Render(),

    これにより、UI の 保存 ボタンの直前に新しい要素がレンダリングされます。

3
  1. managers ディレクトリで、database_manager.hpp にGoします。 addNew()関数のシグネチャを更新して、 home_controller.cppから渡すint newItemPriorityを含めます。

    void addNew(
    bool newItemIsComplete,
    std::string newItemSummary,
    int newItemPriority);
  2. 次に database_manager.cpp にGoし、addNew() の実装を更新します。 関数の引数にint newItemPropertyを追加します。

    void DatabaseManager::addNew(
    bool newItemIsComplete,
    std::string newItemSummary,
    int newItemPriority) {
    ...implementation...
    }

    Itemをデータベースに保存するときに、 priorityプロパティの値を設定するための関数に新しい行を追加します。

    .priority = newItemPriority

    これで、 addNew()の実装は次のようになります。

    void DatabaseManager::addNew(bool newItemIsComplete, std::string newItemSummary, int newItemPriority) {
    auto item = realm::Item {
    .isComplete = newItemIsComplete,
    .summary = std::move(newItemSummary),
    .owner_id = _userId,
    .priority = newItemPriority
    };
    _database->write([&]{
    _database->add(std::move(item));
    });
    }
4

この時点で、アプリケーションを再度ビルドして実行します。 ビルド ディレクトリで、行った変更を反映して実行可能ファイルを再ビルドします。

cmake --build .

そして、アプリを実行します。

./sync_todo /path-to-file/atlasConfig.json

このチュートリアルの前半で作成したアカウントを使用してログインします。 過去に作成した 1 つのアイテムが表示されます。新しいアイテムを追加すると、優先順位を設定できるようになります。優先順位を High にし、アイテムを保存します。

ブラウザで Atlas データページに切り替え、 Itemコレクションを更新します。 これでpriorityフィールドが追加され、 1に設定された新しいアイテムが表示されます。 既存のアイテムにはpriorityフィールドはありません。

コレクション内の 2 つのアイテム
クリックして拡大します

注意

同期が中断されなかった理由

SDK クライアント オブジェクトにプロパティを追加しても重大な変更ではないため、クライアントをリセットする必要はありません。 テンプレート アプリでは開発モードが有効になっているため、クライアント オブジェクトへの変更はサーバー側のスキーマに自動的に反映されます。 詳しくは、「開発モードデータモデルの更新 」を参照してください。

managersディレクトリのdatabase_manager.cppファイルでは、ユーザーのデバイスとアカウントで同期するドキュメントを定義する Flexible Sync サブスクリプションが作成されます。 デフォルトでは、すべてのアイテムをサブスクライブします。 他のユーザーが作成したアイテムは表示できますが、サーバー側のルールによりそれらに書き込むことはできません。 このロジックは、初期サブスクリプションを作成するブロックに記載されています。 アプリを開くときにサブスクライブがない場合は、すべてのItemオブジェクトのサブスクライブを追加します。

_database->subscriptions().update([this](realm::mutable_sync_subscription_set& subs) {
// By default, we show all items.
if (!subs.find(_allItemSubscriptionName)) {
subs.add<realm::Item>(_allItemSubscriptionName);
}
}).get();

toggleSubscriptions()関数では、現在のサブスクライブ状態に応じてサブスクリプションを切り替えます。 UI では、ユーザーはすべてのアイテムを表示するか、自分のアイテムのみを表示するかを切り替えることができます。 この関数内で、 _myItemSubscriptionNameロジックを見つけます。 このサブスクリプション名のサブスクライブがまだ存在しない場合、アプリはowner_idプロパティが認証されたユーザーの ID と一致するすべてのドキュメントにサブスクライブを追加します。

このチュートリアルでは、それを維持し、優先順位が「高」または「重要」とマークされたアイテムのみを同期します。

そのため、 priorityプロパティにint64_tを使用し、UI の優先度レベルを最も重要なものから最も重要でないものの順にラベル付けしました。 最高優先順位(重大)の値は0で、最低優先順位(低)の値は3です。 数値と優先順位プロパティを直接比較できます。

1

サブスクリプションを変更するには、managers ディレクトリにGoし、database_manager.cpp ファイルを開きます。 優先順位が1以下のドキュメントを含むようにクエリ ステートメントを更新します。 これには、優先順位が「重要」( 0 )または「高」( 1 )のアイテムのみを含める必要があります。

if (!subs.find(_myItemSubscriptionName)) {
subs.add<realm::Item>(
_myItemSubscriptionName,
[&](auto &item){
return item.owner_id == _userId && item.priority <= 1;
}
);
}
2

アプリケーションを再度実行します。 このチュートリアルの前半で作成したアカウントを使用してログインします。 Subscriptionボックスで、 Switch to Mineボタンを押します。 SDK がドキュメントコレクションを再同期する最初の瞬間、作成した優先順位の高い新しいアイテムのみが表示されます。 バックグラウンドで同期された新しい項目で UI を再レンダリングするには、マウスを移動するか、矢印キーを使用する必要がある場合があります。

最初に作成したアイテム ドキュメントは、 priorityフィールドがないため、デバイスに表示されません。 このアイテムをデバイスと同期する場合は、Atlas UI でドキュメントを編集し、 priorityフィールドに値を追加できます。

Tip

開発者モードが有効になっている場合にサブスクリプションを変更する

このチュートリアルでは、サブスクリプションを変更し、優先順位フィールドを初めてクエリすると、フィールドは Device Sync Collection Queryable Fieldsに自動的に追加されます。 これは、テンプレート アプリで開発モードがデフォルトで有効になっているために発生します。 開発モードが有効になっていない場合、クライアント側の同期クエリで使用するには、フィールドをクエリ可能なフィールドとして手動で追加する必要があります。

詳細については、「クエリ可能なフィールド 」を参照してください。

機能をさらにテストしたい場合は、さまざまな優先順位のアイテムを作成できます。 優先順位の低い新しいアイテムがアイテム リストに一時的に表示され、その後消えます。 同期エラー ハンドラーは、この動作を説明するメッセージを提供します。

A sync error occurred. Message:
"Client attempted a write that is not allowed; it has been reverted"

このシナリオでは、SDK はアイテムをローカルに作成し、バックエンドと同期した後、サブスクライブ ルールを満たしていないため書き込みを元に戻します。

注意

既知の UI の問題

エラー モーダルが表示されており、エラー モーダルを閉じる前にターミナル内のアイテム リストの上にマウスを移動すると、UI のレンダリングが中断されます。 これは、FTXUI ライブラリの制限に関連しています。 この問題が発生した場合は、 ctrl + cを使用してアプリを終了し、再実行してください。 この問題を回避するには、マウスを移動する前に Enter キーを使用してエラー モーダルのDismissボタンを押します。

既存の SDK オブジェクトにプロパティを追加することは重大じゃない変更であり、 開発モード によりスキーマの変更がサーバー側に反映されるようになります。

注意

フィードバックの共有

ではどのようにGoしましたか。 ページ右下にあるRate this pageウィジェットを使用して、有効性を評価します。 またはGithub リポジトリ に問題を報告する 問題が発生した場合は、。

次へ

Atlas アプリケーション サービスとは