-
Notifications
You must be signed in to change notification settings - Fork 88
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
(DOCSP-26735): C++: Add a Quick Start page #2575
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change | ||||
---|---|---|---|---|---|---|
@@ -0,0 +1,169 @@ | ||||||
#include <catch2/catch_test_macros.hpp> | ||||||
#include <thread> | ||||||
#include <future> | ||||||
#include <string> | ||||||
// :snippet-start: includes | ||||||
#include <cpprealm/sdk.hpp> | ||||||
// :snippet-end: | ||||||
|
||||||
// :replace-start: { | ||||||
// "terms": { | ||||||
// "Local_": "", | ||||||
// "Sync_": "", | ||||||
// "userId.c_str()": "userId" | ||||||
// } | ||||||
// } | ||||||
|
||||||
static const std::string APP_ID = "cpp-tester-uliix"; | ||||||
|
||||||
struct Local_Todo : realm::object<Local_Todo> { | ||||||
realm::persisted<std::string> name; | ||||||
realm::persisted<std::string> status; | ||||||
|
||||||
static constexpr auto schema = realm::schema("Local_Todo", | ||||||
realm::property<&Local_Todo::name>("name"), | ||||||
realm::property<&Local_Todo::status>("status")); | ||||||
}; | ||||||
|
||||||
// :snippet-start: model | ||||||
struct Sync_Todo : realm::object<Sync_Todo> { | ||||||
realm::persisted<realm::object_id> _id{realm::object_id::generate()}; | ||||||
realm::persisted<std::string> name; | ||||||
realm::persisted<std::string> status; | ||||||
// The ownerId property stores the user.identifier() of a | ||||||
// logged-in user. Omit this property for the non-sync example. | ||||||
realm::persisted<std::string> ownerId; | ||||||
|
||||||
static constexpr auto schema = realm::schema("Sync_Todo", | ||||||
realm::property<&Sync_Todo::_id, true>("_id"), | ||||||
realm::property<&Sync_Todo::name>("name"), | ||||||
realm::property<&Sync_Todo::status>("status"), | ||||||
realm::property<&Sync_Todo::ownerId>("ownerId")); | ||||||
}; | ||||||
// :snippet-end: | ||||||
|
||||||
TEST_CASE("local quick start", "[realm][write]") { | ||||||
// :snippet-start: realm-open | ||||||
auto realm = realm::open<Local_Todo>(); | ||||||
// :snippet-end: | ||||||
|
||||||
// :snippet-start: create-todo | ||||||
auto todo = Local_Todo { | ||||||
.name = "Create my first todo item", | ||||||
.status = "In Progress" | ||||||
}; | ||||||
|
||||||
realm.write([&realm, &todo] { | ||||||
realm.add(todo); | ||||||
}); | ||||||
// :snippet-end: | ||||||
|
||||||
// :snippet-start: get-all-todos | ||||||
auto todos = realm.objects<Local_Todo>(); | ||||||
// :snippet-end: | ||||||
CHECK(todos.size() == 1); | ||||||
|
||||||
// :snippet-start: filter | ||||||
auto todosInProgress = todos.where([](auto const& todo) { | ||||||
return todo.status == "In Progress"; | ||||||
}); | ||||||
// :snippet-end: | ||||||
CHECK(todosInProgress.size() == 1); | ||||||
|
||||||
// :snippet-start: watch-for-changes | ||||||
auto token = todo.observe([&](auto&& change) { | ||||||
try { | ||||||
if (change.error) { | ||||||
rethrow_exception(change.error); | ||||||
} | ||||||
if (change.is_deleted) { | ||||||
std::cout << "The object was deleted.\n"; | ||||||
} else { | ||||||
for (auto& propertyChange : change.property_changes) { | ||||||
std::cout << "The object's " << propertyChange.name << " property has changed.\n"; | ||||||
CHECK(propertyChange.name == "status"); // :remove: | ||||||
} | ||||||
} | ||||||
} catch (std::exception const& e) { | ||||||
std::cerr << "Error: " << e.what() << "\n"; | ||||||
} | ||||||
}); | ||||||
// :snippet-end: | ||||||
|
||||||
// :snippet-start: modify-write-block | ||||||
auto todoToUpdate = todosInProgress[0]; | ||||||
realm.write([&realm, &todoToUpdate] { | ||||||
todoToUpdate.status = "Complete"; | ||||||
}); | ||||||
// :snippet-end: | ||||||
CHECK(*todoToUpdate.status == "Complete"); | ||||||
|
||||||
// :snippet-start: delete | ||||||
realm.write([&realm, &todo] { | ||||||
realm.remove(todo); | ||||||
}); | ||||||
// :snippet-end: | ||||||
} | ||||||
|
||||||
TEST_CASE("sync quick start", "[realm][write][sync]") { | ||||||
// :snippet-start: connect-to-backend | ||||||
auto app = realm::App(APP_ID); | ||||||
// :snippet-end: | ||||||
|
||||||
// :snippet-start: authenticate-user | ||||||
auto user = app.login(realm::App::credentials::anonymous()).get_future().get(); | ||||||
// :snippet-end: | ||||||
|
||||||
// :snippet-start: open-synced-realm | ||||||
auto sync_config = user.flexible_sync_configuration(); | ||||||
auto synced_realm_ref = realm::async_open<Sync_Todo>(sync_config).get_future().get(); | ||||||
auto realm = synced_realm_ref.resolve(); | ||||||
// :remove-start: | ||||||
// Remove any existing subscriptions before adding the one for this example | ||||||
auto clearInitialSubscriptions = realm.subscriptions().update([](auto &subs) { | ||||||
subs.clear(); | ||||||
}).get_future().get(); | ||||||
CHECK(clearInitialSubscriptions == true); | ||||||
CHECK(realm.subscriptions().size() == 0); | ||||||
// :remove-end: | ||||||
// For this example, get the userId for the Flexible Sync query | ||||||
auto userId = user.identifier(); | ||||||
auto subscriptions = realm.subscriptions(); | ||||||
auto updateSubscriptionSuccess = subscriptions.update([&](realm::mutable_sync_subscription_set &subs) { | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Does this work?
Suggested change
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It seems that works in above where I'm clearing all subscriptions, but when I try to use it with
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Ok, nevermind! |
||||||
subs.add<Sync_Todo>("todos", [&userId](auto &obj) { | ||||||
// For this example, get only Sync_Todo items where the ownerId | ||||||
// property value is equal to the userId of the logged-in user. | ||||||
return obj.ownerId == userId; | ||||||
}); | ||||||
}).get_future().get(); | ||||||
// :snippet-end: | ||||||
CHECK(updateSubscriptionSuccess == true); | ||||||
|
||||||
// The C++ SDK is currently missing a constructor to store a std::string | ||||||
// So convert the userId std::string to a character array for persisting. | ||||||
// TODO: Remove this and use the userId directly when the constructor is added. | ||||||
// :snippet-start: write-to-synced-realm | ||||||
auto todo = Sync_Todo { | ||||||
.name = "Create a Sync todo item", | ||||||
.status = "In Progress", | ||||||
.ownerId = userId.c_str() | ||||||
}; | ||||||
|
||||||
realm.write([&realm, &todo] { | ||||||
realm.add(todo); | ||||||
}); | ||||||
|
||||||
auto todos = realm.objects<Sync_Todo>(); | ||||||
// :snippet-end: | ||||||
CHECK(todos.size() == 1); | ||||||
|
||||||
// The C++ SDK does not yet expose `waitForUpload` and `waitForDownload` | ||||||
// so add a delay to prevent the connection from terminating while syncing | ||||||
sleep(5); | ||||||
realm.write([&realm, &todo] { | ||||||
realm.remove(todo); | ||||||
}); | ||||||
sleep(5); | ||||||
} | ||||||
|
||||||
// :replace-end: |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
auto user = app.login(realm::App::credentials::anonymous()).get_future().get(); |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
auto app = realm::App(APP_ID); |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
auto todo = Todo { | ||
.name = "Create my first todo item", | ||
.status = "In Progress" | ||
}; | ||
|
||
realm.write([&realm, &todo] { | ||
realm.add(todo); | ||
}); |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
realm.write([&realm, &todo] { | ||
realm.remove(todo); | ||
}); |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
auto todosInProgress = todos.where([](auto const& todo) { | ||
return todo.status == "In Progress"; | ||
}); |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
auto todos = realm.objects<Todo>(); |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
#include <cpprealm/sdk.hpp> |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
struct Todo : realm::object<Todo> { | ||
realm::persisted<realm::object_id> _id{realm::object_id::generate()}; | ||
realm::persisted<std::string> name; | ||
realm::persisted<std::string> status; | ||
// The ownerId property stores the user.identifier() of a | ||
// logged-in user. Omit this property for the non-sync example. | ||
realm::persisted<std::string> ownerId; | ||
|
||
static constexpr auto schema = realm::schema("Todo", | ||
realm::property<&Todo::_id, true>("_id"), | ||
realm::property<&Todo::name>("name"), | ||
realm::property<&Todo::status>("status"), | ||
realm::property<&Todo::ownerId>("ownerId")); | ||
}; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
auto todoToUpdate = todosInProgress[0]; | ||
realm.write([&realm, &todoToUpdate] { | ||
todoToUpdate.status = "Complete"; | ||
}); |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
auto sync_config = user.flexible_sync_configuration(); | ||
auto synced_realm_ref = realm::async_open<Todo>(sync_config).get_future().get(); | ||
auto realm = synced_realm_ref.resolve(); | ||
// For this example, get the userId for the Flexible Sync query | ||
auto userId = user.identifier(); | ||
auto subscriptions = realm.subscriptions(); | ||
auto updateSubscriptionSuccess = subscriptions.update([&](realm::mutable_sync_subscription_set &subs) { | ||
subs.add<Todo>("todos", [&userId](auto &obj) { | ||
// For this example, get only Todo items where the ownerId | ||
// property value is equal to the userId of the logged-in user. | ||
return obj.ownerId == userId; | ||
}); | ||
}).get_future().get(); |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
auto realm = realm::open<Todo>(); |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
auto token = todo.observe([&](auto&& change) { | ||
try { | ||
if (change.error) { | ||
rethrow_exception(change.error); | ||
} | ||
if (change.is_deleted) { | ||
std::cout << "The object was deleted.\n"; | ||
} else { | ||
for (auto& propertyChange : change.property_changes) { | ||
std::cout << "The object's " << propertyChange.name << " property has changed.\n"; | ||
} | ||
} | ||
} catch (std::exception const& e) { | ||
std::cerr << "Error: " << e.what() << "\n"; | ||
} | ||
}); |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
auto todo = Todo { | ||
.name = "Create a Sync todo item", | ||
.status = "In Progress", | ||
.ownerId = userId | ||
}; | ||
|
||
realm.write([&realm, &todo] { | ||
realm.add(todo); | ||
}); | ||
|
||
auto todos = realm.objects<Todo>(); |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,5 +1,5 @@ | ||
.. note:: | ||
|
||
Flexible Sync does not support all the query operators available in Realm | ||
Query Language and LINQ. See :ref:`Flexible Sync RQL Limitations | ||
<flexible-sync-rql-limitations>` for details. | ||
Query Language and the SDK's query engine. See :ref:`Flexible Sync RQL | ||
Limitations <flexible-sync-rql-limitations>` for details. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@cbush
If I replace this
delete
block with this code, instead:I get this error:
I would expect it to work because in line 66 above, we verify that
todos
contains an item. I am assuming it has failed because of memory/unique_ptr shenanigans between 66 and here, but I could be misinterpreting this entirely.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nothing in your alternate code sticks out as wrong to me. Might be worth bringing this up with the SDK team to see if this is a known issue?