rhoconnect 3.0.0.beta1
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG +208 -0
- data/CREDITS +38 -0
- data/Gemfile +18 -0
- data/Gemfile.lock +97 -0
- data/LICENSE +75 -0
- data/README.md +10 -0
- data/Rakefile +82 -0
- data/bench/bench +7 -0
- data/bench/bench_runner.rb +112 -0
- data/bench/benchapp/Gemfile +21 -0
- data/bench/benchapp/Gemfile.lock +76 -0
- data/bench/benchapp/Rakefile +22 -0
- data/bench/benchapp/application.rb +39 -0
- data/bench/benchapp/config.ru +36 -0
- data/bench/benchapp/settings/license.key +1 -0
- data/bench/benchapp/settings/settings.yml +20 -0
- data/bench/benchapp/sources/mock_adapter.rb +55 -0
- data/bench/benchapp/sources/queue_mock_adapter.rb +2 -0
- data/bench/benchapp/spec/sources/mock_adapter_spec.rb +25 -0
- data/bench/benchapp/spec/sources/queue_mock_adapter_spec.rb +25 -0
- data/bench/benchapp/spec/spec_helper.rb +42 -0
- data/bench/blobapp/Gemfile +31 -0
- data/bench/blobapp/Gemfile.lock +103 -0
- data/bench/blobapp/Rakefile +25 -0
- data/bench/blobapp/application.rb +44 -0
- data/bench/blobapp/config.ru +36 -0
- data/bench/blobapp/settings/license.key +1 -0
- data/bench/blobapp/settings/settings.yml +16 -0
- data/bench/blobapp/sources/blob_adapter.rb +71 -0
- data/bench/blobapp/spec/sources/blob_adapter_spec.rb +25 -0
- data/bench/blobapp/spec/spec_helper.rb +42 -0
- data/bench/lib/bench/cli.rb +16 -0
- data/bench/lib/bench/logging.rb +13 -0
- data/bench/lib/bench/mock_client.rb +41 -0
- data/bench/lib/bench/result.rb +50 -0
- data/bench/lib/bench/runner.rb +107 -0
- data/bench/lib/bench/session.rb +67 -0
- data/bench/lib/bench/statistics.rb +56 -0
- data/bench/lib/bench/test_data.rb +98 -0
- data/bench/lib/bench/timer.rb +10 -0
- data/bench/lib/bench/utils.rb +49 -0
- data/bench/lib/bench.rb +129 -0
- data/bench/lib/testdata/100-data.txt +148 -0
- data/bench/lib/testdata/5-data.txt +9 -0
- data/bench/lib/testdata/images/icon.ico +0 -0
- data/bench/lib/testdata/images/icon.png +0 -0
- data/bench/lib/testdata/images/loading-Landscape.png +0 -0
- data/bench/lib/testdata/images/loading-LandscapeLeft.png +0 -0
- data/bench/lib/testdata/images/loading-LandscapeRight.png +0 -0
- data/bench/lib/testdata/images/loading-Portrait.png +0 -0
- data/bench/lib/testdata/images/loading-PortraitUpsideDown.png +0 -0
- data/bench/lib/testdata/images/loading.png +0 -0
- data/bench/lib/testdata/images/loading@2x.png +0 -0
- data/bench/run_bench.sh +42 -0
- data/bench/run_blob_script.sh +3 -0
- data/bench/run_cud_script.sh +3 -0
- data/bench/run_query_md_script.sh +3 -0
- data/bench/run_query_only_script.sh +3 -0
- data/bench/run_query_script.sh +3 -0
- data/bench/scripts/blob_cud_script.rb +98 -0
- data/bench/scripts/cud_script.rb +92 -0
- data/bench/scripts/helpers.rb +101 -0
- data/bench/scripts/query_md_script.rb +45 -0
- data/bench/scripts/query_only_script.rb +51 -0
- data/bench/scripts/query_script.rb +45 -0
- data/bench/spec/bench_spec_helper.rb +33 -0
- data/bench/spec/logging_spec.rb +15 -0
- data/bench/spec/mock_adapter_spec.rb +61 -0
- data/bench/spec/mock_client_spec.rb +65 -0
- data/bench/spec/result_spec.rb +61 -0
- data/bench/spec/utils_spec.rb +36 -0
- data/bin/rhoconnect +34 -0
- data/bin/rhoconnect-setup +84 -0
- data/doc/async-jobs.txt +69 -0
- data/doc/authentication.txt +76 -0
- data/doc/benchmarks.txt +168 -0
- data/doc/blob-sync.txt +130 -0
- data/doc/bulk-sync.txt +102 -0
- data/doc/client.txt +432 -0
- data/doc/command-line.txt +210 -0
- data/doc/contributing.txt +60 -0
- data/doc/deploying.txt +82 -0
- data/doc/install.txt +28 -0
- data/doc/introduction.txt +20 -0
- data/doc/licensing.txt +18 -0
- data/doc/metadata.txt +458 -0
- data/doc/migration.txt +182 -0
- data/doc/public/css/print.css +29 -0
- data/doc/public/css/screen.css +257 -0
- data/doc/public/css/style.css +20 -0
- data/doc/push.txt +135 -0
- data/doc/release.txt +41 -0
- data/doc/rest-api.txt +367 -0
- data/doc/source-adapters.txt +325 -0
- data/doc/stats-middleware.txt +69 -0
- data/doc/testing.txt +222 -0
- data/doc/tutorial.txt +315 -0
- data/doc/web-console.txt +35 -0
- data/examples/simple/Rakefile +14 -0
- data/examples/simple/application.rb +27 -0
- data/examples/simple/config.ru +49 -0
- data/examples/simple/settings/license.key +1 -0
- data/examples/simple/settings/settings.yml +23 -0
- data/examples/simple/sources/sample_adapter.rb +5 -0
- data/examples/simple/sources/simple_adapter.rb +5 -0
- data/generators/rhoconnect.rb +119 -0
- data/generators/templates/application/Gemfile +21 -0
- data/generators/templates/application/Rakefile +22 -0
- data/generators/templates/application/application.rb +39 -0
- data/generators/templates/application/config.ru +36 -0
- data/generators/templates/application/settings/license.key +1 -0
- data/generators/templates/application/settings/settings.yml +14 -0
- data/generators/templates/application/spec/spec_helper.rb +42 -0
- data/generators/templates/source/source_adapter.rb +47 -0
- data/generators/templates/source/source_spec.rb +25 -0
- data/install.sh +408 -0
- data/installer/unix-like/rho_connect_install_checkers.rb +140 -0
- data/installer/unix-like/rho_connect_install_constants.rb +51 -0
- data/installer/unix-like/rho_connect_install_debian.rb +63 -0
- data/installer/unix-like/rho_connect_install_dnd.rb +58 -0
- data/installer/unix-like/rho_connect_install_get_params.rb +30 -0
- data/installer/unix-like/rho_connect_install_installers.rb +142 -0
- data/installer/unix-like/rho_connect_install_utilities.rb +85 -0
- data/installer/unix-like/rho_connect_install_yum.rb +63 -0
- data/installer/unix-like/rhoinstaller.rb +89 -0
- data/installer/utils/create_texts.rb +366 -0
- data/installer/utils/install_test.rb +140 -0
- data/installer/windows/EnvVarUpdate.nsh +328 -0
- data/installer/windows/ServiceLib.nsh +369 -0
- data/installer/windows/configUi.ini +44 -0
- data/installer/windows/icon.ico +0 -0
- data/installer/windows/rhosync.nsi +418 -0
- data/installer/windows/uninstall.bat +7 -0
- data/lib/rhoconnect/api/admin/get_api_token.rb +14 -0
- data/lib/rhoconnect/api/admin/get_license_info.rb +8 -0
- data/lib/rhoconnect/api/admin/login.rb +6 -0
- data/lib/rhoconnect/api/admin/reset.rb +10 -0
- data/lib/rhoconnect/api/admin/stats.rb +21 -0
- data/lib/rhoconnect/api/application/bulk_data.rb +7 -0
- data/lib/rhoconnect/api/application/clientcreate.rb +8 -0
- data/lib/rhoconnect/api/application/clientlogin.rb +6 -0
- data/lib/rhoconnect/api/application/clientregister.rb +6 -0
- data/lib/rhoconnect/api/application/clientreset.rb +6 -0
- data/lib/rhoconnect/api/application/query.rb +7 -0
- data/lib/rhoconnect/api/application/queue_updates.rb +6 -0
- data/lib/rhoconnect/api/application/search.rb +6 -0
- data/lib/rhoconnect/api/client/create_client.rb +3 -0
- data/lib/rhoconnect/api/client/delete_client.rb +5 -0
- data/lib/rhoconnect/api/client/get_client_params.rb +3 -0
- data/lib/rhoconnect/api/client/list_client_docs.rb +12 -0
- data/lib/rhoconnect/api/client/list_clients.rb +3 -0
- data/lib/rhoconnect/api/client/ping.rb +7 -0
- data/lib/rhoconnect/api/source/get_adapter.rb +3 -0
- data/lib/rhoconnect/api/source/get_db_doc.rb +7 -0
- data/lib/rhoconnect/api/source/get_source_params.rb +3 -0
- data/lib/rhoconnect/api/source/list_source_docs.rb +10 -0
- data/lib/rhoconnect/api/source/list_sources.rb +15 -0
- data/lib/rhoconnect/api/source/push_deletes.rb +8 -0
- data/lib/rhoconnect/api/source/push_objects.rb +8 -0
- data/lib/rhoconnect/api/source/save_adapter.rb +3 -0
- data/lib/rhoconnect/api/source/set_db_doc.rb +8 -0
- data/lib/rhoconnect/api/source/set_refresh_time.rb +8 -0
- data/lib/rhoconnect/api/source/upload_file.rb +4 -0
- data/lib/rhoconnect/api/user/create_user.rb +7 -0
- data/lib/rhoconnect/api/user/delete_user.rb +9 -0
- data/lib/rhoconnect/api/user/list_users.rb +3 -0
- data/lib/rhoconnect/api/user/update_user.rb +4 -0
- data/lib/rhoconnect/api_token.rb +19 -0
- data/lib/rhoconnect/app.rb +76 -0
- data/lib/rhoconnect/bulk_data/bulk_data.rb +88 -0
- data/lib/rhoconnect/bulk_data/syncdb.index.schema +4 -0
- data/lib/rhoconnect/bulk_data/syncdb.schema +41 -0
- data/lib/rhoconnect/bulk_data.rb +2 -0
- data/lib/rhoconnect/client.rb +96 -0
- data/lib/rhoconnect/client_sync.rb +412 -0
- data/lib/rhoconnect/console/app/helpers/auth_helper.rb +22 -0
- data/lib/rhoconnect/console/app/helpers/extensions.rb +19 -0
- data/lib/rhoconnect/console/app/helpers/helpers.rb +57 -0
- data/lib/rhoconnect/console/app/public/ThickBox.css +649 -0
- data/lib/rhoconnect/console/app/public/home.css +438 -0
- data/lib/rhoconnect/console/app/public/images/foot_logo_rhoconnect.png +0 -0
- data/lib/rhoconnect/console/app/public/images/header_halo.jpg +0 -0
- data/lib/rhoconnect/console/app/public/images/land_separator.gif +0 -0
- data/lib/rhoconnect/console/app/public/images/landing_header.jpg +0 -0
- data/lib/rhoconnect/console/app/public/images/logo_rhoconnect.png +0 -0
- data/lib/rhoconnect/console/app/public/images/rhomobile_rhohub_logo.png +0 -0
- data/lib/rhoconnect/console/app/public/images/tabs_separator.png +0 -0
- data/lib/rhoconnect/console/app/public/jqplot/excanvas.min.js +35 -0
- data/lib/rhoconnect/console/app/public/jqplot/jqplot.barRenderer.min.js +34 -0
- data/lib/rhoconnect/console/app/public/jqplot/jqplot.canvasAxisLabelRenderer.js +187 -0
- data/lib/rhoconnect/console/app/public/jqplot/jqplot.canvasAxisTickRenderer.js +226 -0
- data/lib/rhoconnect/console/app/public/jqplot/jqplot.canvasTextRenderer.js +408 -0
- data/lib/rhoconnect/console/app/public/jqplot/jqplot.categoryAxisRenderer.min.js +34 -0
- data/lib/rhoconnect/console/app/public/jqplot/jqplot.cursor.js +952 -0
- data/lib/rhoconnect/console/app/public/jqplot/jqplot.dateAxisRenderer.js +313 -0
- data/lib/rhoconnect/console/app/public/jqplot/jqplot.dateAxisRenderer.min.js +34 -0
- data/lib/rhoconnect/console/app/public/jqplot/jqplot.pointLabels.min.js +34 -0
- data/lib/rhoconnect/console/app/public/jqplot/jquery-1.4.2.min.js +154 -0
- data/lib/rhoconnect/console/app/public/jqplot/jquery.jqplot.min.css +1 -0
- data/lib/rhoconnect/console/app/public/jqplot/jquery.jqplot.min.js +34 -0
- data/lib/rhoconnect/console/app/public/main.css +7 -0
- data/lib/rhoconnect/console/app/public/reset.css +76 -0
- data/lib/rhoconnect/console/app/public/style.css +2201 -0
- data/lib/rhoconnect/console/app/public/text.txt +0 -0
- data/lib/rhoconnect/console/app/routes/adapter.rb +28 -0
- data/lib/rhoconnect/console/app/routes/auth.rb +29 -0
- data/lib/rhoconnect/console/app/routes/client.rb +31 -0
- data/lib/rhoconnect/console/app/routes/docs.rb +145 -0
- data/lib/rhoconnect/console/app/routes/heroku.rb +19 -0
- data/lib/rhoconnect/console/app/routes/home.rb +63 -0
- data/lib/rhoconnect/console/app/routes/timing.rb +242 -0
- data/lib/rhoconnect/console/app/routes/user.rb +117 -0
- data/lib/rhoconnect/console/app/views/adapter.erb +16 -0
- data/lib/rhoconnect/console/app/views/client.erb +30 -0
- data/lib/rhoconnect/console/app/views/content.erb +14 -0
- data/lib/rhoconnect/console/app/views/doc.erb +8 -0
- data/lib/rhoconnect/console/app/views/docdata.erb +28 -0
- data/lib/rhoconnect/console/app/views/docs.erb +30 -0
- data/lib/rhoconnect/console/app/views/edituser.erb +13 -0
- data/lib/rhoconnect/console/app/views/headermenu.erb +40 -0
- data/lib/rhoconnect/console/app/views/home.erb +24 -0
- data/lib/rhoconnect/console/app/views/index.erb +58 -0
- data/lib/rhoconnect/console/app/views/jqplot.erb +52 -0
- data/lib/rhoconnect/console/app/views/layout.erb +165 -0
- data/lib/rhoconnect/console/app/views/login.erb +26 -0
- data/lib/rhoconnect/console/app/views/newuser.erb +17 -0
- data/lib/rhoconnect/console/app/views/ping.erb +28 -0
- data/lib/rhoconnect/console/app/views/result.erb +11 -0
- data/lib/rhoconnect/console/app/views/rightboxlinks.erb +15 -0
- data/lib/rhoconnect/console/app/views/select_doc.erb +17 -0
- data/lib/rhoconnect/console/app/views/upload_doc.erb +23 -0
- data/lib/rhoconnect/console/app/views/user.erb +29 -0
- data/lib/rhoconnect/console/app/views/users.erb +12 -0
- data/lib/rhoconnect/console/rhoconnect_api.rb +245 -0
- data/lib/rhoconnect/console/server.rb +32 -0
- data/lib/rhoconnect/console.rb +3 -0
- data/lib/rhoconnect/cors.rb +229 -0
- data/lib/rhoconnect/credential.rb +9 -0
- data/lib/rhoconnect/db_adapter.rb +46 -0
- data/lib/rhoconnect/document.rb +49 -0
- data/lib/rhoconnect/dynamic_adapter.rb +91 -0
- data/lib/rhoconnect/generator.rb +1 -0
- data/lib/rhoconnect/jobs/bulk_data_job.rb +203 -0
- data/lib/rhoconnect/jobs/ping_job.rb +46 -0
- data/lib/rhoconnect/jobs/source_job.rb +16 -0
- data/lib/rhoconnect/license.rb +86 -0
- data/lib/rhoconnect/lock_ops.rb +11 -0
- data/lib/rhoconnect/model.rb +414 -0
- data/lib/rhoconnect/ping/android.rb +56 -0
- data/lib/rhoconnect/ping/apple.rb +52 -0
- data/lib/rhoconnect/ping/blackberry.rb +56 -0
- data/lib/rhoconnect/ping.rb +3 -0
- data/lib/rhoconnect/read_state.rb +31 -0
- data/lib/rhoconnect/rho_indifferent_access.rb +88 -0
- data/lib/rhoconnect/server/views/index.erb +13 -0
- data/lib/rhoconnect/server.rb +286 -0
- data/lib/rhoconnect/source.rb +289 -0
- data/lib/rhoconnect/source_adapter.rb +123 -0
- data/lib/rhoconnect/source_sync.rb +302 -0
- data/lib/rhoconnect/stats/middleware.rb +20 -0
- data/lib/rhoconnect/stats/record.rb +108 -0
- data/lib/rhoconnect/store.rb +232 -0
- data/lib/rhoconnect/tasks.rb +350 -0
- data/lib/rhoconnect/test_methods.rb +220 -0
- data/lib/rhoconnect/user.rb +95 -0
- data/lib/rhoconnect/version.rb +3 -0
- data/lib/rhoconnect/x_domain_session_wrapper.rb +53 -0
- data/lib/rhoconnect.rb +285 -0
- data/rhoconnect.gemspec +67 -0
- data/spec/api/admin/api_token_spec.rb +14 -0
- data/spec/api/admin/get_api_token_spec.rb +36 -0
- data/spec/api/admin/get_license_info_spec.rb +38 -0
- data/spec/api/admin/reset_spec.rb +22 -0
- data/spec/api/admin/stats_spec.rb +66 -0
- data/spec/api/api_helper.rb +21 -0
- data/spec/api/application/rhoconnect_api_spec.rb +548 -0
- data/spec/api/client/create_client_spec.rb +13 -0
- data/spec/api/client/delete_client_spec.rb +13 -0
- data/spec/api/client/get_client_params_spec.rb +18 -0
- data/spec/api/client/list_client_docs_spec.rb +32 -0
- data/spec/api/client/list_clients_spec.rb +22 -0
- data/spec/api/client/ping_spec.rb +23 -0
- data/spec/api/rhosync_api_spec.rb.orig +606 -0
- data/spec/api/source/adapter_spec.rb +29 -0
- data/spec/api/source/get_db_doc_spec.rb +21 -0
- data/spec/api/source/get_source_params_spec.rb +32 -0
- data/spec/api/source/list_source_docs_spec.rb +25 -0
- data/spec/api/source/list_sources_spec.rb +26 -0
- data/spec/api/source/push_deletes_spec.rb +18 -0
- data/spec/api/source/push_objects_spec.rb +27 -0
- data/spec/api/source/set_db_doc_spec.rb +19 -0
- data/spec/api/source/set_refresh_time_spec.rb +43 -0
- data/spec/api/source/upload_file_spec.rb +26 -0
- data/spec/api/user/create_user_spec.rb +16 -0
- data/spec/api/user/delete_user_spec.rb +36 -0
- data/spec/api/user/list_users_spec.rb +30 -0
- data/spec/api/user/update_user_spec.rb +31 -0
- data/spec/api_token_spec.rb +14 -0
- data/spec/app_spec.rb +18 -0
- data/spec/apps/emptyapp/application.rb +27 -0
- data/spec/apps/emptyapp/settings/license.key +1 -0
- data/spec/apps/emptyapp/settings/settings.yml +14 -0
- data/spec/apps/rhotestapp/Rakefile +1 -0
- data/spec/apps/rhotestapp/application.rb +19 -0
- data/spec/apps/rhotestapp/config.ru +1 -0
- data/spec/apps/rhotestapp/settings/apple_fake_cert.pem +1 -0
- data/spec/apps/rhotestapp/settings/license.key +1 -0
- data/spec/apps/rhotestapp/settings/settings.yml +36 -0
- data/spec/apps/rhotestapp/sources/base_adapter.rb +9 -0
- data/spec/apps/rhotestapp/sources/fixed_schema_adapter.rb +28 -0
- data/spec/apps/rhotestapp/sources/sample_adapter.rb +71 -0
- data/spec/apps/rhotestapp/sources/simple_adapter.rb +41 -0
- data/spec/apps/rhotestapp/sources/sub_adapter.rb +7 -0
- data/spec/apps/rhotestapp/vendor/mygem-0.1.0/lib/mygem/mygem.rb +8 -0
- data/spec/apps/rhotestapp/vendor/mygem-0.1.0/lib/mygem.rb +1 -0
- data/spec/bulk_data/bulk_data_spec.rb +97 -0
- data/spec/client_spec.rb +124 -0
- data/spec/client_sync_spec.rb +774 -0
- data/spec/doc/base.html +72 -0
- data/spec/doc/doc_spec.rb +376 -0
- data/spec/doc/footer.html +4 -0
- data/spec/doc/header.html +30 -0
- data/spec/document_spec.rb +31 -0
- data/spec/dynamic_adapter_spec.rb +43 -0
- data/spec/factories/factories.rb +17 -0
- data/spec/generator/generator_spec.rb +58 -0
- data/spec/generator/generator_spec_helper.rb +9 -0
- data/spec/jobs/bulk_data_job_spec.rb +125 -0
- data/spec/jobs/ping_job_spec.rb +102 -0
- data/spec/jobs/source_job_spec.rb +29 -0
- data/spec/license_spec.rb +66 -0
- data/spec/model_spec.rb +273 -0
- data/spec/perf/bulk_data_perf_spec.rb +32 -0
- data/spec/perf/perf_spec_helper.rb +50 -0
- data/spec/perf/store_perf_spec.rb +27 -0
- data/spec/ping/android_spec.rb +91 -0
- data/spec/ping/apple_spec.rb +70 -0
- data/spec/ping/blackberry_spec.rb +62 -0
- data/spec/read_state_spec.rb +35 -0
- data/spec/rhosync_spec.rb +75 -0
- data/spec/server/cors_spec.rb +287 -0
- data/spec/server/server_spec.rb +470 -0
- data/spec/server/x_domain_session_wrapper_spec.rb +150 -0
- data/spec/source_adapter_spec.rb +125 -0
- data/spec/source_spec.rb +114 -0
- data/spec/source_sync_spec.rb +328 -0
- data/spec/spec.opts +4 -0
- data/spec/spec_helper.rb +231 -0
- data/spec/stats/middleware_spec.rb +53 -0
- data/spec/stats/record_spec.rb +92 -0
- data/spec/store_spec.rb +251 -0
- data/spec/support/shared_examples.rb +168 -0
- data/spec/sync_states_spec.rb +72 -0
- data/spec/test_methods_spec.rb +134 -0
- data/spec/testdata/1000-data.txt +1414 -0
- data/spec/testdata/compressed/compress-data.txt +1 -0
- data/spec/testdata/upload1.txt +1 -0
- data/spec/testdata/upload2.txt +1 -0
- data/spec/user_spec.rb +139 -0
- data/tasks/redis.rake +206 -0
- metadata +706 -0
data/doc/rest-api.txt
ADDED
@@ -0,0 +1,367 @@
|
|
1
|
+
RhoConnect REST API
|
2
|
+
===
|
3
|
+
The RhoConnect REST API allows you to control, monitor, and debug a running RhoConnect application using a simple HTTP API.
|
4
|
+
|
5
|
+
Below we describe the REST API using ruby sample code.
|
6
|
+
|
7
|
+
## API Errors
|
8
|
+
All API calls will return http 200 and requested data (if applied). Otherwise, API will return http error code and specific error message in the http message body.
|
9
|
+
|
10
|
+
:::ruby
|
11
|
+
def handle_api_error(error_message)
|
12
|
+
@errors ||= []
|
13
|
+
begin
|
14
|
+
yield
|
15
|
+
rescue RestClient::Exception => re
|
16
|
+
if re.response.body.nil? or re.response.body.length == 0
|
17
|
+
@errors << "#{error_message}: [#{re.http_code}] #{re.message}"
|
18
|
+
else
|
19
|
+
@errors << "#{error_message}: #{re.response.body}"
|
20
|
+
end
|
21
|
+
rescue Exception => e
|
22
|
+
@errors << "#{error_message}: #{e.message}"
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
handle_api_error("Can't get license information") do
|
27
|
+
@license_info = JSON.parse(
|
28
|
+
RestClient.post(
|
29
|
+
"#{server}/api/get_license_info",
|
30
|
+
{ :api_token => @token }.to_json,
|
31
|
+
:content_type => :json
|
32
|
+
).body
|
33
|
+
)
|
34
|
+
end
|
35
|
+
|
36
|
+
## API Methods
|
37
|
+
|
38
|
+
### `get_api_token`
|
39
|
+
Before you can use RhoConnect API you should get API token:
|
40
|
+
|
41
|
+
:::ruby
|
42
|
+
require 'rest_client'
|
43
|
+
require 'json'
|
44
|
+
|
45
|
+
server = "http://localhost:9292"
|
46
|
+
login = "rhoadmin"
|
47
|
+
password = ""
|
48
|
+
|
49
|
+
res = RestClient.post("#{server}/login", { :login => login, :password => password }.to_json, :content_type => :json)
|
50
|
+
rhoconnect_session_cookie = 'rhoconnect_session=' + res.cookies['rhoconnect_session']
|
51
|
+
token = RestClient.post("#{server}/api/get_api_token",'',{ 'Cookie' => rhoconnect_session_cookie })
|
52
|
+
|
53
|
+
### `get_license_info`
|
54
|
+
Returns license information of the currently used license
|
55
|
+
|
56
|
+
:::ruby
|
57
|
+
license_info = RestClient.post(
|
58
|
+
"#{server}/api/get_license_info",
|
59
|
+
{:api_token => token}.to_json, :content_type => :json
|
60
|
+
).body
|
61
|
+
|
62
|
+
### `reset`
|
63
|
+
Reset the server: flush db and re-bootstrap server
|
64
|
+
|
65
|
+
:::ruby
|
66
|
+
RestClient.post("#{server}/api/reset",
|
67
|
+
{ :api_token => token }.to_json,
|
68
|
+
:content_type => :json
|
69
|
+
)
|
70
|
+
|
71
|
+
### `ping`
|
72
|
+
Sends PUSH message to all devices of the specified user:
|
73
|
+
|
74
|
+
:::ruby
|
75
|
+
# :message - message which will be used to display notification popup dialog on the device
|
76
|
+
# :badge - iphone specific badge
|
77
|
+
# :sound - name of the sound file to play upon receiving PUSH notification
|
78
|
+
# :vibrate - number of seconds to vibrate upon receiving PUSH notification
|
79
|
+
# :sources - list of data source names to be synced upon receiving PUSH notification
|
80
|
+
ping_params = {
|
81
|
+
:api_token => token,
|
82
|
+
:user_id => user_id,
|
83
|
+
:sources => source_name,
|
84
|
+
:message => 'hello world',
|
85
|
+
:vibrate => 2000,
|
86
|
+
:sound => 'hello.mp3'
|
87
|
+
}
|
88
|
+
|
89
|
+
RestClient.post(
|
90
|
+
"#{server}/api/ping",ping_params.to_json,
|
91
|
+
:content_type => :json
|
92
|
+
)
|
93
|
+
|
94
|
+
### `push_objects`
|
95
|
+
Push new objects or object updates to RhoConnect. These changes will be sent to device next time it synchronizes.
|
96
|
+
|
97
|
+
**NOTE: you may use [ping](/rhoconnect/push) to notify client and trigger sync.**
|
98
|
+
|
99
|
+
:::ruby
|
100
|
+
# list of objects in the canonical hash of hashes structure
|
101
|
+
data = {
|
102
|
+
'5' => {
|
103
|
+
'name' => 'iPhone'
|
104
|
+
}
|
105
|
+
}
|
106
|
+
RestClient.post(
|
107
|
+
"#{server}/api/push_objects",
|
108
|
+
{
|
109
|
+
:api_token => token,
|
110
|
+
:user_id => user_id,
|
111
|
+
:source_id => source_name,
|
112
|
+
:objects => data
|
113
|
+
}.to_json,
|
114
|
+
:content_type => :json
|
115
|
+
)
|
116
|
+
|
117
|
+
### `push_deletes`
|
118
|
+
Delete objects from RhoConnect. These objects will be deleted from the device the next time it synchronizes.
|
119
|
+
|
120
|
+
**NOTE: You may use [ping](/rhoconnect/push) to notify client and trigger sync.**
|
121
|
+
|
122
|
+
:::ruby
|
123
|
+
# object_ids is an array of objects to be deleted
|
124
|
+
RestClient.post(
|
125
|
+
"/api/push_deletes",
|
126
|
+
{
|
127
|
+
:api_token => api_token,
|
128
|
+
:user_id => user_id,
|
129
|
+
:source_id => source_name,
|
130
|
+
:objects => object_ids
|
131
|
+
}.to_json,
|
132
|
+
:content_type => :json
|
133
|
+
)
|
134
|
+
|
135
|
+
### `list_users`
|
136
|
+
List users registered with this RhoConnect application.
|
137
|
+
|
138
|
+
:::ruby
|
139
|
+
users = RestClient.post(
|
140
|
+
"#{server}/api/list_users",
|
141
|
+
{ :api_token => token }.to_json,
|
142
|
+
:content_type => :json
|
143
|
+
).body
|
144
|
+
|
145
|
+
### `create_user`
|
146
|
+
Create a user in this RhoConnect application.
|
147
|
+
|
148
|
+
:::ruby
|
149
|
+
RestClient.post("#{server}/api/create_user",
|
150
|
+
{
|
151
|
+
:api_token => token,
|
152
|
+
:attributes => {
|
153
|
+
:login => login,
|
154
|
+
:password => password
|
155
|
+
}
|
156
|
+
}.to_json,
|
157
|
+
:content_type => :json
|
158
|
+
)
|
159
|
+
|
160
|
+
### `delete_user`
|
161
|
+
Delete User and all associated devices from the RhoConnect application.
|
162
|
+
|
163
|
+
:::ruby
|
164
|
+
RestClient.post(
|
165
|
+
"#{server}/api/delete_user",
|
166
|
+
{
|
167
|
+
:api_token => token,
|
168
|
+
:user_id => user_id
|
169
|
+
}.to_json,
|
170
|
+
:content_type => :json
|
171
|
+
)
|
172
|
+
|
173
|
+
### `list_clients`
|
174
|
+
List clients (devices) associated with given user.
|
175
|
+
|
176
|
+
:::ruby
|
177
|
+
clients = RestClient.post("#{server}/api/list_clients",
|
178
|
+
{
|
179
|
+
:api_token => token,
|
180
|
+
:user_id => user_id
|
181
|
+
}.to_json,
|
182
|
+
:content_type => :json
|
183
|
+
).body
|
184
|
+
|
185
|
+
Returns list of client ids.
|
186
|
+
|
187
|
+
### `create_client`
|
188
|
+
Creates a client (device) for a given user.
|
189
|
+
|
190
|
+
:::ruby
|
191
|
+
RestClient.post(
|
192
|
+
"#{server}/api/create_client",
|
193
|
+
{
|
194
|
+
:api_token => token,
|
195
|
+
:user_id => user_id
|
196
|
+
}.to_json,
|
197
|
+
:content_type => :json
|
198
|
+
).body
|
199
|
+
|
200
|
+
### `delete_client`
|
201
|
+
Deletes the specified client (device).
|
202
|
+
|
203
|
+
:::ruby
|
204
|
+
RestClient.post(
|
205
|
+
"#{server}/api/delete_client",
|
206
|
+
{
|
207
|
+
:api_token => token,
|
208
|
+
:user_id => user_id,
|
209
|
+
:client_id => client_id
|
210
|
+
}.to_json,
|
211
|
+
:content_type => :json
|
212
|
+
)
|
213
|
+
|
214
|
+
### `get_client_params`
|
215
|
+
Returns client (device) attributes, such as `device_type`, `device_pin`, `device_port`. These attributes used by [RhoConnect push](/rhoconnect/push).
|
216
|
+
|
217
|
+
:::ruby
|
218
|
+
RestClient.post(
|
219
|
+
"#{server}/api/get_client_params",
|
220
|
+
{
|
221
|
+
:api_token => token,
|
222
|
+
:client_id => client_id
|
223
|
+
}.to_json,
|
224
|
+
:content_type => :json
|
225
|
+
).body
|
226
|
+
|
227
|
+
### `list_client_docs`
|
228
|
+
Returns list of document keys associated with particular client. These documents are used by the server to sync data with the client.
|
229
|
+
CD (:cd) - client document; represents the state of the client (set of all objects on the given client).
|
230
|
+
|
231
|
+
:::ruby
|
232
|
+
RestClient.post(
|
233
|
+
"#{server}/api/list_client_docs",
|
234
|
+
{
|
235
|
+
:api_token => token,
|
236
|
+
:source_id => source_id,
|
237
|
+
:client_id => client_id
|
238
|
+
}.to_json,
|
239
|
+
:content_type => :json
|
240
|
+
).body
|
241
|
+
|
242
|
+
### `list_sources`
|
243
|
+
Return list of source adapters for this RhoConnect application.
|
244
|
+
|
245
|
+
:::ruby
|
246
|
+
sources = RestClient.post("#{server}/api/list_sources",
|
247
|
+
{
|
248
|
+
:api_token => token,
|
249
|
+
:partition_type => partition
|
250
|
+
}.to_json,
|
251
|
+
:content_type => :json
|
252
|
+
).body
|
253
|
+
|
254
|
+
### `get_source_params`
|
255
|
+
Return attributes associated with a given source:
|
256
|
+
|
257
|
+
* `name` - name of the data source
|
258
|
+
* `poll_interval` - query poll interval; defines how often RhoConnect will call source adapter to query for new data, set to -1 to disable polling, 0 to always poll
|
259
|
+
* `partition_type` - to share data across all users, set partition to :app; otherwise use `:user` partition (default)
|
260
|
+
* `sync_type` - set to `:bulk_only` to disable `:incremental` sync; regular sync is `:incremental` (default)
|
261
|
+
* `queue` - name of the queue for both query and create/update/delete (CUD) jobs (used if no specific queues not specified)
|
262
|
+
* `query_queue` - name of query queue
|
263
|
+
* `cud_queue` - name of CUD queue
|
264
|
+
|
265
|
+
**NOTE: query or create/update/delete methods of the source adapter will be executed [asynchronously](/rhoconnect/async-jobs) if a queue name is defined.**
|
266
|
+
|
267
|
+
:::ruby
|
268
|
+
attributes = RestClient.post("#{server}/api/get_source_params",
|
269
|
+
{
|
270
|
+
:api_token => token,
|
271
|
+
:source_id => source_id
|
272
|
+
}.to_json,
|
273
|
+
:content_type => :json
|
274
|
+
).body
|
275
|
+
|
276
|
+
### `set_refresh_time`
|
277
|
+
Sets source poll interval to "current time plus x seconds".
|
278
|
+
|
279
|
+
:::ruby
|
280
|
+
RestClient.post(
|
281
|
+
"/api/set_refresh_time",
|
282
|
+
{
|
283
|
+
:api_token => @api_token,
|
284
|
+
:source_name => source_name,
|
285
|
+
:user_name => user,
|
286
|
+
:refresh_time => 100
|
287
|
+
}.to_json,
|
288
|
+
:content_type => :json
|
289
|
+
)
|
290
|
+
|
291
|
+
This will set the refresh time to 100 seconds from the current time. Calling `set_refresh_time` with no `:refresh_time` will trigger a refresh on the sync request for the source.
|
292
|
+
|
293
|
+
### `list_source_docs`
|
294
|
+
Return list of document keys associated with given source and user.
|
295
|
+
|
296
|
+
If `:user_id` set to '*', this call will return list of keys for 'shared' documents.
|
297
|
+
|
298
|
+
MD(:md) - master document; represents state of the backend (set of all objects for the given app/user/source on the backend service).
|
299
|
+
|
300
|
+
:::ruby
|
301
|
+
docs = RestClient.post(
|
302
|
+
"#{server}/api/list_source_docs",
|
303
|
+
{
|
304
|
+
:api_token => token,
|
305
|
+
:source_id => source_id,
|
306
|
+
:user_id => user_id
|
307
|
+
}.to_json,
|
308
|
+
:content_type => :json
|
309
|
+
).body
|
310
|
+
|
311
|
+
### `get_db_doc`
|
312
|
+
Return content of a given document (client or source).
|
313
|
+
|
314
|
+
:::ruby
|
315
|
+
res = RestClient.post(
|
316
|
+
"#{server}/api/get_db_doc",
|
317
|
+
{
|
318
|
+
:api_token => token,
|
319
|
+
:doc => doc,
|
320
|
+
:data_type => data_type
|
321
|
+
}.to_json,
|
322
|
+
:content_type => :json
|
323
|
+
).body
|
324
|
+
|
325
|
+
`:data_type` should be 'string' for the documents containing single string (size or token docs); otherwise this call will return hash of hashes.
|
326
|
+
|
327
|
+
### `set_db_doc`
|
328
|
+
Sets the content of the specified server document. Data should be either a string or hash of hashes. Data type should be set accordingly.
|
329
|
+
|
330
|
+
:::ruby
|
331
|
+
RestClient.post(
|
332
|
+
"#{server}/api/set_db_doc",
|
333
|
+
{
|
334
|
+
:api_token => token,
|
335
|
+
:doc => doc,
|
336
|
+
:data => data,
|
337
|
+
:data_type => data_type
|
338
|
+
}.to_json,
|
339
|
+
:content_type => :json
|
340
|
+
)
|
341
|
+
|
342
|
+
### `stats`
|
343
|
+
Retrieves stats for a given metric key:
|
344
|
+
|
345
|
+
:::ruby
|
346
|
+
RestClient.post(
|
347
|
+
"#{server}/api/stats",
|
348
|
+
{
|
349
|
+
:api_token => @api_token,
|
350
|
+
:metric => 'foo',
|
351
|
+
:start => 0,
|
352
|
+
:finish => -1
|
353
|
+
}.to_json,
|
354
|
+
:content_type => :json
|
355
|
+
)
|
356
|
+
|
357
|
+
Retrieves a list of metric keys matching a given pattern. This supports 'glob' or '*' style pattern matching. For example, all metric keys associated with 'Product' source adapter methods:
|
358
|
+
|
359
|
+
:::ruby
|
360
|
+
RestClient.post(
|
361
|
+
"#{server}/api/stats",
|
362
|
+
{
|
363
|
+
:api_token => @api_token,
|
364
|
+
:names => 'sources:*:Product'
|
365
|
+
}.to_json,
|
366
|
+
:content_type => :json
|
367
|
+
)
|
@@ -0,0 +1,325 @@
|
|
1
|
+
RhoConnect Source Adapters
|
2
|
+
===
|
3
|
+
|
4
|
+
Connecting to a backend service with RhoConnect requires that you write a small amount of Ruby code for the query, create, update and delete operations of your particular enterprise backend. The collection of the Ruby code for these operations we refer to as a "source" or "source adapter".
|
5
|
+
|
6
|
+
## Generate Source Adapter
|
7
|
+
|
8
|
+
Adding a new source adapter to your RhoConnect application is simple:
|
9
|
+
|
10
|
+
:::term
|
11
|
+
$ cd storeserver
|
12
|
+
$ rhoconnect source product
|
13
|
+
|
14
|
+
This will generate a new ruby class called `sources/product.rb`:
|
15
|
+
|
16
|
+
:::ruby
|
17
|
+
class Product < SourceAdapter
|
18
|
+
def initialize(source)
|
19
|
+
super(source)
|
20
|
+
end
|
21
|
+
|
22
|
+
def login
|
23
|
+
# TODO: Login to your data source here if necessary
|
24
|
+
end
|
25
|
+
|
26
|
+
def query
|
27
|
+
# TODO: Query your backend data source and assign the records
|
28
|
+
# to a nested hash structure called @result. For example:
|
29
|
+
# @result = {
|
30
|
+
# "1"=>{"name"=>"Acme", "industry"=>"Electronics"},
|
31
|
+
# "2"=>{"name"=>"Best", "industry"=>"Software"}
|
32
|
+
# }
|
33
|
+
raise SourceAdapterException.new("Please provide some code to read records from the backend data source")
|
34
|
+
end
|
35
|
+
|
36
|
+
def sync
|
37
|
+
super
|
38
|
+
end
|
39
|
+
|
40
|
+
def create(create_hash)
|
41
|
+
# TODO: Create a new record in your backend data source
|
42
|
+
# If your rhodes rhom object contains image/binary data
|
43
|
+
# (has the image_uri attribute), then a blob will be provided
|
44
|
+
raise "Please provide some code to create a single record in the backend data source using the create_hash"
|
45
|
+
end
|
46
|
+
|
47
|
+
def update(update_hash)
|
48
|
+
# TODO: Update an existing record in your backend data source
|
49
|
+
raise "Please provide some code to update a single record in the backend data source using the update_hash"
|
50
|
+
end
|
51
|
+
|
52
|
+
def delete(delete_hash)
|
53
|
+
# TODO: write some code here if applicable
|
54
|
+
# be sure to have a hash key and value for "object"
|
55
|
+
# for now, we'll say that its OK to not have a delete operation
|
56
|
+
# raise "Please provide some code to delete a single object in the backend application using the object_id"
|
57
|
+
end
|
58
|
+
|
59
|
+
def logoff
|
60
|
+
# TODO: Logout from the data source if necessary
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
It also adds a spec file `spec/sources/product_spec.rb` and updates `settings/settings.yml` with the product adapter to the sources section with some default options:
|
65
|
+
|
66
|
+
:::yaml
|
67
|
+
:sources:
|
68
|
+
Product:
|
69
|
+
:poll_interval: 300
|
70
|
+
|
71
|
+
## Source Adapter API
|
72
|
+
The source adapter interface is described below, your source adapter can use any of these methods to interact with your backend service.
|
73
|
+
|
74
|
+
### `login`
|
75
|
+
Login to your backend service (optional).
|
76
|
+
|
77
|
+
:::ruby
|
78
|
+
def login
|
79
|
+
MyWebService.login(current_user.login)
|
80
|
+
end
|
81
|
+
|
82
|
+
### `logoff`
|
83
|
+
Logoff from your backend service (optional).
|
84
|
+
|
85
|
+
:::ruby
|
86
|
+
def logoff
|
87
|
+
MyWebService.logoff(current_user.login)
|
88
|
+
end
|
89
|
+
|
90
|
+
### `query(params = nil)`
|
91
|
+
Query your backend service and build a hash of hashes (required).
|
92
|
+
|
93
|
+
**NOTE: This method must assign `@result` to a hash of hashes. If @result is `nil` or `{}`, the master document will be erased from redis.**
|
94
|
+
|
95
|
+
:::ruby
|
96
|
+
def query
|
97
|
+
parsed = JSON.parse(RestClient.get("#{@base}.json").body)
|
98
|
+
|
99
|
+
@result = {}
|
100
|
+
parsed.each do |item|
|
101
|
+
@result[item["product"]["id"].to_s] = item["product"]
|
102
|
+
end if parsed
|
103
|
+
end
|
104
|
+
|
105
|
+
### `search(params)`
|
106
|
+
Search your backend based on params and build a hash of hashes (optional). Similar to query, however the master document accumulates the data in `@result` instead of replacing when it runs.
|
107
|
+
|
108
|
+
:::ruby
|
109
|
+
def search(params)
|
110
|
+
parsed = JSON.parse(RestClient.get("#{@base}.json").body)
|
111
|
+
|
112
|
+
@result = {}
|
113
|
+
parsed.each do |item|
|
114
|
+
if item["product"]["name"].downcase == params['name'].downcase
|
115
|
+
@result[item["product"]["id"].to_s] = item["product"]
|
116
|
+
end
|
117
|
+
end if parsed
|
118
|
+
end
|
119
|
+
|
120
|
+
Next, you will need to add search to your Rhodes application. For details, see the [Rhodes search section](/rhodes/synchronization#filtering-datasets-with-search).
|
121
|
+
|
122
|
+
### `create(create_hash)`
|
123
|
+
Create a new record in the backend (optional).
|
124
|
+
|
125
|
+
**NOTE: RhoConnect can establish a 'link' between the local record id provided by the client and the new record id provided by the backend service. To enable this link, return the new record id as a string.**
|
126
|
+
|
127
|
+
:::ruby
|
128
|
+
def create(create_hash)
|
129
|
+
res = MyWebService.create(create_hash)
|
130
|
+
|
131
|
+
# return new product id so we establish a client link
|
132
|
+
res.new_id
|
133
|
+
end
|
134
|
+
|
135
|
+
### `update(update_hash)`
|
136
|
+
Update an existing record in the backend (optional).
|
137
|
+
|
138
|
+
:::ruby
|
139
|
+
def update(update_hash)
|
140
|
+
end
|
141
|
+
|
142
|
+
### `delete(delete_hash)`
|
143
|
+
Delete an existing record in the backend (optional).
|
144
|
+
|
145
|
+
:::ruby
|
146
|
+
def delete(delete_hash)
|
147
|
+
MyWebService.delete(delete_hash['id'])
|
148
|
+
end
|
149
|
+
|
150
|
+
### `current_user`
|
151
|
+
Returns the current user which called the adapter. For example, you could filter results for a specific user in your query method:
|
152
|
+
|
153
|
+
:::ruby
|
154
|
+
def query
|
155
|
+
@result = MyWebService.get_records_for_user(current_user.login)
|
156
|
+
end
|
157
|
+
|
158
|
+
### `stash_result`
|
159
|
+
Saves the current state of `@result` to redis and assigns it to `nil`. Typically this is used when your adapter has to paginate through backend service data.
|
160
|
+
|
161
|
+
:::ruby
|
162
|
+
def query
|
163
|
+
@result = {}
|
164
|
+
('a'..'z').each_with_index do |letter,i|
|
165
|
+
@result ||= {}
|
166
|
+
@result.merge!( DictionaryService.get_records_for(letter) )
|
167
|
+
stash_result if i % 2
|
168
|
+
end
|
169
|
+
end
|
170
|
+
|
171
|
+
## Data Partitioning
|
172
|
+
Data is stored in RhoConnect using [redis sets](http://redis.io/commands#set). The `@result` hash from the `query` method is stored in redis and referred to as the Master Document or MD.
|
173
|
+
|
174
|
+
The MD is referenced in RhoConnect by a corresponding partition. Source adapters can partition data in two ways: user and app. As you might have guessed, user partitioning stores a copy of the source adapter MD for each user (one copy shared across all devices for a user).
|
175
|
+
|
176
|
+
Likewise, app partitioning stores one copy of the source adapter MD for the entire application (all users and devices share the same data). App partitioning can be particularly useful if you have source adapters which retrieve large amounts of data that is fixed from user to user, for example a global product catalog. Using app partitioning wherever possible ***greatly reduces*** the amount of data in redis.
|
177
|
+
|
178
|
+
### User Partition
|
179
|
+
User partitioning is the default scheme for source adapters, however you can explicitly define it in `settings/settings.yml` with:
|
180
|
+
|
181
|
+
:::yaml
|
182
|
+
:sources:
|
183
|
+
Product:
|
184
|
+
:poll_interval: 300
|
185
|
+
:partition_type: user
|
186
|
+
|
187
|
+
### App Partition
|
188
|
+
Enable app partitioning the same way:
|
189
|
+
|
190
|
+
:::yaml
|
191
|
+
:sources:
|
192
|
+
Product:
|
193
|
+
:poll_interval: 300
|
194
|
+
:partition_type: app
|
195
|
+
|
196
|
+
Now you have a single copy of the `Product` source adapter dataset for all users.
|
197
|
+
|
198
|
+
## Pass Through
|
199
|
+
RhoConnect provides a simple way to keep data out of redis. If you have sensitive data that you do not want saved in redis, add the pass_through option in settings/settings.yml for each source:
|
200
|
+
|
201
|
+
:::yaml
|
202
|
+
:sources:
|
203
|
+
Product:
|
204
|
+
:pass_through: true
|
205
|
+
|
206
|
+
**NOTE: When running query or search the entire data set will be returned from your backend service. **
|
207
|
+
|
208
|
+
## Store API
|
209
|
+
RhoConnect provides a simple redis interface for saving/retrieving arbitrary data. This is useful if you want to save data in your application to be used later (i.e. in an async job or a subsequent source adapter execution).
|
210
|
+
|
211
|
+
:::ruby
|
212
|
+
Store.put_value('hello','world')
|
213
|
+
|
214
|
+
Store.get_value('hello') #=> 'world'
|
215
|
+
|
216
|
+
# You can store nested hashes too!
|
217
|
+
Store.put_data(
|
218
|
+
'mydata',
|
219
|
+
{
|
220
|
+
'1' => { 'hello' => 'world' }
|
221
|
+
}
|
222
|
+
)
|
223
|
+
|
224
|
+
Store.get_data('mydata') #=> { '1' => { 'hello' => 'world' } }
|
225
|
+
|
226
|
+
## Handling Exceptions
|
227
|
+
If your source adapter raises an instance of `SourceAdapterException`, the resulting message will be sent to the client's sync callback(in `@params['error_message']`). See the rhodes [sync exception handling docs](/rhodes/synchronization#handling-exceptions) for more details.
|
228
|
+
|
229
|
+
You can use `SourceAdapterException` as a convenient way to notify your application of various error conditions.
|
230
|
+
|
231
|
+
For example, your delete method might check the web service HTTP response code was 200 to make sure the record was deleted:
|
232
|
+
|
233
|
+
:::ruby
|
234
|
+
def delete(delete_hash)
|
235
|
+
rest_result = RestClient.delete("#{@base}/#{delete_hash['id']}")
|
236
|
+
if rest_result.code != 200
|
237
|
+
raise SourceAdapterException.new("Error deleting record.")
|
238
|
+
end
|
239
|
+
end
|
240
|
+
|
241
|
+
**NOTE: When your adapter method raises an exception, no data is removed from the adapter's master document.**
|
242
|
+
|
243
|
+
The following exceptions are provided for convenience:
|
244
|
+
|
245
|
+
### `SourceAdapterLoginException`
|
246
|
+
Useful to raise in your adapter's login method if it failed.
|
247
|
+
|
248
|
+
### `SourceAdapterLogoffException`
|
249
|
+
Similar to login, raise this if your adapter's logoff failed.
|
250
|
+
|
251
|
+
### `SourceAdapterServerTimeoutException`
|
252
|
+
Raise if your backend service connection times out.
|
253
|
+
|
254
|
+
### `SourceAdapterServerErrorException`
|
255
|
+
Raise this if your backend service returns a non-successful response.
|
256
|
+
|
257
|
+
|
258
|
+
## Handling Conflicts
|
259
|
+
|
260
|
+
Handling conflicts in RhoConnect follows the same pattern as handling exceptions. Once your adapter method has detected a conflict, you can raise a `SourceAdapterObjectConflictError` which will be sent to your application's sync callback.
|
261
|
+
|
262
|
+
### `SourceAdapterObjectConflictError`
|
263
|
+
Raise this if your adapter has detected a conflict.
|
264
|
+
|
265
|
+
:::ruby
|
266
|
+
def update(update_hash)
|
267
|
+
obj_id = update_hash['id']
|
268
|
+
update_hash.delete('id')
|
269
|
+
rest_result = RestClient.put("#{@base}/#{obj_id}",:product => update_hash)
|
270
|
+
if rest_result.code != 200
|
271
|
+
raise SourceAdapterObjectConflictError.new("Conflict detected updating the object.")
|
272
|
+
end
|
273
|
+
end
|
274
|
+
|
275
|
+
## Sample Adapter
|
276
|
+
Here's a complete example of how the completed [product adapter might look](https://github.com/rhomobile/store-server/blob/master/sources/product.rb):
|
277
|
+
|
278
|
+
:::ruby
|
279
|
+
require 'json'
|
280
|
+
require 'rest_client'
|
281
|
+
|
282
|
+
class Product < SourceAdapter
|
283
|
+
|
284
|
+
def initialize(source)
|
285
|
+
@base = 'http://rhostore.heroku.com/products'
|
286
|
+
super(source)
|
287
|
+
end
|
288
|
+
|
289
|
+
def query(params=nil)
|
290
|
+
rest_result = RestClient.get("#{@base}.json").body
|
291
|
+
|
292
|
+
if rest_result.code != 200
|
293
|
+
raise SourceAdapterException.new("Error connecting!")
|
294
|
+
end
|
295
|
+
parsed = JSON.parse(rest_result)
|
296
|
+
|
297
|
+
@result={}
|
298
|
+
parsed.each do |item|
|
299
|
+
@result[item["product"]["id"].to_s] = item["product"]
|
300
|
+
end if parsed
|
301
|
+
end
|
302
|
+
|
303
|
+
def create(create_hash)
|
304
|
+
res = RestClient.post(@base,:product => create_hash)
|
305
|
+
|
306
|
+
# After create we are redirected to the new record.
|
307
|
+
# We need to get the id of that record and return
|
308
|
+
# it as part of create so rhoconnect can establish a link
|
309
|
+
# from its temporary object on the client to this newly
|
310
|
+
# created object on the server
|
311
|
+
JSON.parse(
|
312
|
+
RestClient.get("#{res.headers[:location]}.json").body
|
313
|
+
)["product"]["id"]
|
314
|
+
end
|
315
|
+
|
316
|
+
def update(update_hash)
|
317
|
+
obj_id = update_hash['id']
|
318
|
+
update_hash.delete('id')
|
319
|
+
RestClient.put("#{@base}/#{obj_id}",:product => update_hash)
|
320
|
+
end
|
321
|
+
|
322
|
+
def delete(delete_hash)
|
323
|
+
RestClient.delete("#{@base}/#{delete_hash['id']}")
|
324
|
+
end
|
325
|
+
end
|