rhoconnect 3.3.6 → 3.4.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (152) hide show
  1. data/CHANGELOG.md +40 -4
  2. data/Gemfile +2 -2
  3. data/Gemfile.lock +27 -25
  4. data/bench/benchapp/Gemfile +7 -27
  5. data/bench/benchapp/config.ru +9 -31
  6. data/bench/blobapp/Gemfile +7 -27
  7. data/bench/blobapp/config.ru +9 -29
  8. data/bench/lib/bench.rb +8 -1
  9. data/bench/lib/bench/test_data.rb +4 -1
  10. data/bench/scripts/blob_cud_script.rb +4 -0
  11. data/bench/scripts/cud_script.rb +7 -1
  12. data/bench/scripts/helpers.rb +1 -1
  13. data/bench/scripts/test_query_script.rb +20 -7
  14. data/bench/spec/bench_spec_helper.rb +3 -1
  15. data/bin/rhoconnect +22 -12
  16. data/commands/{commands/dtach_commands → dtach}/dtach_about.rb +0 -0
  17. data/commands/{commands/dtach_commands → dtach}/dtach_install.rb +0 -0
  18. data/commands/{commands/redis_commands → dtach}/redis_attach.rb +0 -0
  19. data/commands/execute.rb +14 -15
  20. data/commands/generators/update.rb +26 -0
  21. data/commands/{commands/redis_commands → redis}/redis_about.rb +0 -0
  22. data/commands/redis/redis_download.rb +13 -0
  23. data/commands/redis/redis_install.rb +26 -0
  24. data/commands/{commands/redis_commands → redis}/redis_make.rb +0 -0
  25. data/commands/{commands/redis_commands → redis}/redis_restart.rb +3 -2
  26. data/commands/{commands/redis_commands → redis}/redis_start.rb +0 -0
  27. data/commands/{commands/redis_commands → redis}/redis_startbg.rb +0 -0
  28. data/commands/{commands/redis_commands → redis}/redis_stop.rb +3 -2
  29. data/commands/{commands/rhoconnect → rhoconnect}/clean_start.rb +0 -0
  30. data/commands/{commands/rhoconnect → rhoconnect}/config.rb +7 -2
  31. data/commands/{commands/rhoconnect → rhoconnect}/create_user.rb +0 -0
  32. data/commands/{commands/rhoconnect → rhoconnect}/delete_device.rb +0 -0
  33. data/commands/{commands/rhoconnect → rhoconnect}/delete_user.rb +0 -0
  34. data/commands/{commands/rhoconnect → rhoconnect}/flushdb.rb +4 -4
  35. data/commands/{commands/rhoconnect → rhoconnect}/get_token.rb +0 -0
  36. data/commands/{commands/rhoconnect → rhoconnect}/reset.rb +0 -0
  37. data/commands/{commands/rhoconnect → rhoconnect}/reset_refresh.rb +0 -0
  38. data/commands/{commands/rhoconnect → rhoconnect}/restart.rb +0 -0
  39. data/commands/{commands/rhoconnect → rhoconnect}/secret.rb +0 -0
  40. data/commands/{commands/rhoconnect → rhoconnect}/set_admin_password.rb +0 -0
  41. data/commands/{commands/rhoconnect → rhoconnect}/spec.rb +0 -0
  42. data/commands/rhoconnect/start.rb +27 -0
  43. data/commands/{commands/rhoconnect → rhoconnect}/startbg.rb +0 -0
  44. data/commands/{commands/rhoconnect → rhoconnect}/startdebug.rb +2 -2
  45. data/commands/{commands/rhoconnect → rhoconnect}/stop.rb +3 -4
  46. data/commands/{commands/rhoconnect → rhoconnect}/version.rb +0 -0
  47. data/commands/{commands/rhoconnect → rhoconnect}/web.rb +0 -0
  48. data/commands/rhoconnect_attach/attach.rb +10 -0
  49. data/commands/rhoconnect_console/console.rb +16 -0
  50. data/commands/{commands/rhoconnect → rhoconnect_console}/console_helper.rb +0 -0
  51. data/commands/{commands/rhoconnect → rhoconnect_war}/war.rb +0 -0
  52. data/commands/{commands/redis_commands → utilities}/redis_runner.rb +22 -19
  53. data/commands/utilities/utilities.rb +6 -0
  54. data/doc/benchmarks.txt +2 -2
  55. data/doc/bulk-sync.txt +12 -1
  56. data/doc/client-java.txt +3 -3
  57. data/doc/client-objc.txt +1 -1
  58. data/doc/client.txt +5 -5
  59. data/doc/command-line.txt +80 -135
  60. data/doc/deploying.txt +119 -12
  61. data/doc/extending-rhoconnect-server.txt +1 -1
  62. data/doc/heroku-addon.txt +119 -23
  63. data/doc/install.txt +101 -39
  64. data/doc/java-plugin.txt +2 -2
  65. data/doc/licensing.txt +1 -1
  66. data/doc/plugin-intro.txt +3 -1
  67. data/doc/preparing-production.txt +4 -4
  68. data/doc/public/cli.txt +2 -2
  69. data/doc/push-backend-setup.txt +11 -1
  70. data/doc/push-client-setup.txt +72 -2
  71. data/doc/push-server-setup.txt +129 -8
  72. data/doc/rails-plugin.txt +245 -40
  73. data/doc/rest-api.txt +10 -6
  74. data/doc/rhoconnect-calculator.txt +237 -0
  75. data/doc/rhoconnect-redis-stack.txt +35 -0
  76. data/doc/session-and-configuration.txt +24 -0
  77. data/doc/settings.txt +51 -41
  78. data/doc/source-adapters.txt +45 -45
  79. data/doc/stats-middleware.txt +2 -2
  80. data/doc/supported-platforms.txt +6 -6
  81. data/doc/testing.txt +2 -2
  82. data/doc/tutorial.txt +63 -63
  83. data/examples/simple/Gemfile +7 -35
  84. data/examples/simple/config.ru +8 -26
  85. data/examples/simple/sources/product.rb +6 -6
  86. data/generators/rhoconnect.rb +5 -0
  87. data/generators/templates/application/Gemfile +7 -37
  88. data/generators/templates/application/Rakefile +8 -0
  89. data/generators/templates/application/config.ru +12 -31
  90. data/generators/templates/application/rcgemfile +44 -0
  91. data/generators/templates/application/settings/settings.yml +7 -5
  92. data/install.sh +4 -4
  93. data/installer/unix-like/create_texts.rb +7 -2
  94. data/installer/unix-like/rho_connect_install_constants.rb +2 -2
  95. data/installer/unix-like/rho_connect_install_installers.rb +1 -16
  96. data/lib/rhoconnect.rb +51 -38
  97. data/lib/rhoconnect/api/app/query.rb +4 -1
  98. data/lib/rhoconnect/api/app/search.rb +4 -1
  99. data/lib/rhoconnect/api/client/list_client_docs.rb +3 -1
  100. data/lib/rhoconnect/api/user/ping.rb +1 -5
  101. data/lib/rhoconnect/application/init.rb +43 -0
  102. data/lib/rhoconnect/async.rb +11 -6
  103. data/lib/rhoconnect/client_sync.rb +30 -37
  104. data/lib/rhoconnect/document.rb +4 -0
  105. data/lib/rhoconnect/graph_helper.rb +74 -56
  106. data/lib/rhoconnect/middleware/helpers.rb +4 -0
  107. data/lib/rhoconnect/ping.rb +1 -0
  108. data/lib/rhoconnect/ping/gcm.rb +58 -0
  109. data/lib/rhoconnect/predefined_adapters/bench_adapter.rb +7 -1
  110. data/lib/rhoconnect/source.rb +70 -56
  111. data/lib/rhoconnect/source_sync.rb +33 -5
  112. data/lib/rhoconnect/store.rb +358 -110
  113. data/lib/rhoconnect/user.rb +8 -0
  114. data/lib/rhoconnect/utilities.rb +16 -14
  115. data/lib/rhoconnect/version.rb +1 -1
  116. data/lib/rhoconnect/web-console/models/client.js +1 -1
  117. data/lib/rhoconnect/web-console/public/UNVR67bold.ttf +0 -0
  118. data/lib/rhoconnect/web-console/public/bootstrap.css +6 -0
  119. data/lib/rhoconnect/web-console/public/logo.png +0 -0
  120. data/lib/rhoconnect/web-console/server.rb +13 -11
  121. data/lib/rhoconnect/web-console/templates/index.erb +5 -5
  122. data/lib/rhoconnect/web-console/templates/jqplot.erb +1 -0
  123. data/lib/rhoconnect/web-console/views/doc.js +0 -4
  124. data/lib/rhoconnect/web-console/views/home.js +2 -1
  125. data/lib/rhoconnect/web-console/views/new_ping.js +11 -6
  126. data/lib/rhoconnect/web-console/views/stats.js +9 -5
  127. data/rhoconnect.gemspec +6 -4
  128. data/spec/api/app/fast_update_spec.rb +2 -2
  129. data/spec/api/source/get_source_params_spec.rb +1 -0
  130. data/spec/apps/rhotestapp/settings/settings.yml +5 -5
  131. data/spec/client_sync_spec.rb +3 -14
  132. data/spec/perf/perf_spec_helper.rb +11 -7
  133. data/spec/perf/store_perf_spec.rb +88 -11
  134. data/spec/ping/gcm_spec.rb +99 -0
  135. data/spec/server/server_spec.rb +7 -0
  136. data/spec/server/stats_spec.rb +9 -2
  137. data/spec/source_sync_spec.rb +29 -0
  138. data/spec/spec_helper.rb +40 -38
  139. data/spec/stats/record_spec.rb +18 -9
  140. data/spec/store_spec.rb +128 -19
  141. data/spec/testdata/10000-data.txt +0 -0
  142. data/spec/testdata/5-data.txt +0 -0
  143. data/spec/testdata/5000-data.txt +0 -0
  144. data/tasks/jasmine.rake +1 -0
  145. data/tasks/redis.rake +16 -13
  146. metadata +71 -39
  147. data/commands/commands/redis_commands/redis_download.rb +0 -33
  148. data/commands/commands/redis_commands/redis_install.rb +0 -26
  149. data/commands/commands/rhoconnect/attach.rb +0 -8
  150. data/commands/commands/rhoconnect/console.rb +0 -15
  151. data/commands/commands/rhoconnect/start.rb +0 -18
  152. data/commands/utilities/dtach_installed.rb +0 -10
@@ -62,44 +62,44 @@ Generating a source adapter named "product" will generate a new ruby class calle
62
62
  def initialize(source)
63
63
  super(source)
64
64
  end
65
-
65
+
66
66
  def login
67
67
  # TODO: Login to your data source here if necessary
68
68
  end
69
-
69
+
70
70
  def query
71
- # TODO: Query your backend data source and assign the records
71
+ # TODO: Query your backend data source and assign the records
72
72
  # to a nested hash structure called @result. For example:
73
- # @result = {
73
+ # @result = {
74
74
  # "1"=>{"name"=>"Acme", "industry"=>"Electronics"},
75
75
  # "2"=>{"name"=>"Best", "industry"=>"Software"}
76
76
  # }
77
77
  raise SourceAdapterException.new("Please provide some code to read records from the backend data source")
78
78
  end
79
-
79
+
80
80
  def sync
81
81
  super
82
82
  end
83
-
83
+
84
84
  def create(create_hash)
85
85
  # TODO: Create a new record in your backend data source
86
- # If your rhodes rhom object contains image/binary data
86
+ # If your rhodes rhom object contains image/binary data
87
87
  # (has the image_uri attribute), then a blob will be provided
88
88
  raise "Please provide some code to create a single record in the backend data source using the create_hash"
89
89
  end
90
-
90
+
91
91
  def update(update_hash)
92
92
  # TODO: Update an existing record in your backend data source
93
93
  raise "Please provide some code to update a single record in the backend data source using the update_hash"
94
94
  end
95
-
95
+
96
96
  def delete(delete_hash)
97
97
  # TODO: write some code here if applicable
98
98
  # be sure to have a hash key and value for "object"
99
99
  # for now, we'll say that its OK to not have a delete operation
100
100
  # raise "Please provide some code to delete a single object in the backend application using the object_id"
101
101
  end
102
-
102
+
103
103
  def logoff
104
104
  # TODO: Logout from the data source if necessary
105
105
  end
@@ -108,8 +108,8 @@ Generating a source adapter named "product" will generate a new ruby class calle
108
108
  It also adds a corresponding [rspec](http://rspec.info/) file `spec/sources/product_spec.rb` and updates `settings/settings.yml` with the product adapter to the sources section with some default options:
109
109
 
110
110
  :::yaml
111
- :sources:
112
- Product:
111
+ :sources:
112
+ Product:
113
113
  :poll_interval: 300
114
114
 
115
115
  ## Source Adapter API
@@ -162,7 +162,7 @@ Search your backend based on params and build a hash of hashes (optional). Simi
162
162
  end
163
163
 
164
164
  Next, you will need to add search to your Rhodes application. For details, see the [Rhodes search section](/rhodes/synchronization#filtering-datasets-with-search).
165
-
165
+
166
166
  ### `create(create_hash)`
167
167
  Create a new record in the backend (optional).
168
168
 
@@ -190,7 +190,7 @@ Delete an existing record in the backend (optional).
190
190
  def delete(delete_hash)
191
191
  MyWebService.delete(delete_hash['id'])
192
192
  end
193
-
193
+
194
194
  ### `current_user`
195
195
  Returns the current user which called the adapter. For example, you could filter results for a specific user in your query method:
196
196
 
@@ -198,7 +198,7 @@ Returns the current user which called the adapter. For example, you could filte
198
198
  def query
199
199
  @result = MyWebService.get_records_for_user(current_user.login)
200
200
  end
201
-
201
+
202
202
  ### `stash_result`
203
203
  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.
204
204
 
@@ -208,14 +208,14 @@ Saves the current state of `@result` to redis and assigns it to `nil`. Typicall
208
208
  ('a'..'z').each_with_index do |letter,i|
209
209
  @result ||= {}
210
210
  @result.merge!( DictionaryService.get_records_for(letter) )
211
- stash_result if i % 2
211
+ stash_result if i % 2 == 0
212
212
  end
213
213
  end
214
214
 
215
215
  ## Data Partitioning
216
- 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.
216
+ 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.
217
217
 
218
- 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).
218
+ 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).
219
219
 
220
220
  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.
221
221
 
@@ -223,17 +223,17 @@ Likewise, app partitioning stores one copy of the source adapter MD for the enti
223
223
  User partitioning is the default scheme for source adapters, however you can explicitly define it in `settings/settings.yml` with:
224
224
 
225
225
  :::yaml
226
- :sources:
227
- Product:
226
+ :sources:
227
+ Product:
228
228
  :poll_interval: 300
229
229
  :partition_type: user
230
230
 
231
231
  ### App Partition
232
232
  Enable app partitioning the same way:
233
-
233
+
234
234
  :::yaml
235
- :sources:
236
- Product:
235
+ :sources:
236
+ Product:
237
237
  :poll_interval: 300
238
238
  :partition_type: app
239
239
 
@@ -241,10 +241,10 @@ Now you have a single copy of the `Product` source adapter dataset for all users
241
241
 
242
242
  ## Pass Through
243
243
  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:
244
-
244
+
245
245
  :::yaml
246
- :sources:
247
- Product:
246
+ :sources:
247
+ Product:
248
248
  :pass_through: true
249
249
 
250
250
  **NOTE: When running query or search the entire data set will be returned from your backend service. **
@@ -266,7 +266,7 @@ RhoConnect provides a simple redis interface for saving/retrieving arbitrary dat
266
266
  )
267
267
 
268
268
  Store.get_data('mydata') #=> { '1' => { 'hello' => 'world' } }
269
-
269
+
270
270
  ## Handling Exceptions
271
271
  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.
272
272
 
@@ -275,7 +275,7 @@ You can use `SourceAdapterException` as a convenient way to notify your applicat
275
275
  For example, your delete method might check the web service HTTP response code was 200 to make sure the record was deleted:
276
276
 
277
277
  :::ruby
278
- def delete(delete_hash)
278
+ def delete(delete_hash)
279
279
  rest_result = RestClient.delete("#{@base}/#{delete_hash['id']}")
280
280
  if rest_result.code != 200
281
281
  raise SourceAdapterException.new("Error deleting record.")
@@ -307,9 +307,9 @@ Handling conflicts in RhoConnect follows the same pattern as handling exceptions
307
307
  Raise this if your adapter has detected a conflict.
308
308
 
309
309
  :::ruby
310
- def update(update_hash)
310
+ def update(update_hash)
311
311
  obj_id = update_hash['id']
312
- update_hash.delete('id')
312
+ update_hash.delete('id')
313
313
  rest_result = RestClient.put("#{@base}/#{obj_id}",:product => update_hash)
314
314
  if rest_result.code != 200
315
315
  raise SourceAdapterObjectConflictError.new("Conflict detected updating the object.")
@@ -324,12 +324,12 @@ Here's a complete example of how the completed [product adapter might look](http
324
324
  require 'rest_client'
325
325
 
326
326
  class Product < SourceAdapter
327
-
327
+
328
328
  def initialize(source)
329
- @base = 'http://rhostore.heroku.com/products'
329
+ @base = 'http://rhostore.herokuapp.com/products'
330
330
  super(source)
331
331
  end
332
-
332
+
333
333
  def query(params=nil)
334
334
  rest_result = RestClient.get("#{@base}.json").body
335
335
 
@@ -341,29 +341,29 @@ Here's a complete example of how the completed [product adapter might look](http
341
341
  @result={}
342
342
  parsed.each do |item|
343
343
  @result[item["product"]["id"].to_s] = item["product"]
344
- end if parsed
344
+ end if parsed
345
345
  end
346
-
346
+
347
347
  def create(create_hash)
348
348
  res = RestClient.post(@base,:product => create_hash)
349
-
350
- # After create we are redirected to the new record.
351
- # We need to get the id of that record and return
352
- # it as part of create so rhoconnect can establish a link
353
- # from its temporary object on the client to this newly
349
+
350
+ # After create we are redirected to the new record.
351
+ # We need to get the id of that record and return
352
+ # it as part of create so rhoconnect can establish a link
353
+ # from its temporary object on the client to this newly
354
354
  # created object on the server
355
355
  JSON.parse(
356
356
  RestClient.get("#{res.headers[:location]}.json").body
357
357
  )["product"]["id"]
358
358
  end
359
-
360
- def update(update_hash)
359
+
360
+ def update(update_hash)
361
361
  obj_id = update_hash['id']
362
- update_hash.delete('id')
362
+ update_hash.delete('id')
363
363
  RestClient.put("#{@base}/#{obj_id}",:product => update_hash)
364
364
  end
365
-
366
- def delete(delete_hash)
365
+
366
+ def delete(delete_hash)
367
367
  RestClient.delete("#{@base}/#{delete_hash['id']}")
368
368
  end
369
369
  end
@@ -46,12 +46,12 @@ A complete config.ru might look like:
46
46
  Now just restart your rhoconnect application:
47
47
 
48
48
  :::term
49
- $ rake rhoconnect:restart
49
+ $ rhoconnect restart
50
50
 
51
51
  And navigate to the 'Statistics' tab in your RhoConnect console:
52
52
 
53
53
  :::term
54
- $ rake rhoconnect:web
54
+ $ rhoconnect web
55
55
 
56
56
  ## Stats Console
57
57
  You should see graphs, organized by categories:
@@ -19,7 +19,7 @@ Supported Platforms
19
19
  <td> ruby-1.8.7-p370 </td>
20
20
  <td> ree-1.8.7-2012.02 </td>
21
21
  <td> ruby-1.9.2-p320 </td>
22
- <td> ruby-1.9.3-p194 </td>
22
+ <td> ruby-1.9.3-p286 </td>
23
23
  <td> jruby-1.6.7 </td>
24
24
  <td>Development &<br/>Production</td>
25
25
  </tr>
@@ -29,7 +29,7 @@ Supported Platforms
29
29
  <td> ruby-1.8.7-p370 </td>
30
30
  <td> ree-1.8.7-2012.02 </td>
31
31
  <td> ruby-1.9.2-p320 </td>
32
- <td> ruby-1.9.3-p194 </td>
32
+ <td> ruby-1.9.3-p286 </td>
33
33
  <td> jruby-1.6.7 </td>
34
34
  <td>Development &<br/>Production</td>
35
35
  </tr>
@@ -39,7 +39,7 @@ Supported Platforms
39
39
  <td> ruby-1.8.7-p370 </td>
40
40
  <td class='tbd'> TBD </td>
41
41
  <td class='tbd'> TBD </td>
42
- <td> ruby-1.9.3-p194 </td>
42
+ <td> ruby-1.9.3-p286 </td>
43
43
  <td class='tbd'> TBD </td>
44
44
  <td>Development</td>
45
45
  </tr>
@@ -60,14 +60,14 @@ RhoConnect for Windows is supported only in development environments. The compon
60
60
 
61
61
  RhoConnect for Linux and Mac OS X is supported for both development and production environments. The components you should have for this environment are:
62
62
 
63
- * Ruby 1.9.3-p194
64
- * Nginx HTTP server (1.2.x)
63
+ * Ruby 1.9.3
64
+ * Nginx HTTP server (1.3.x)
65
65
  * Redis data store (2.4.x)
66
66
  * Thin application server
67
67
  * RhoConnect gem with all required dependencies
68
68
 
69
+
69
70
  ## Known Issues
70
71
 
71
- * Windows platform: only pre-release (~> 1.0.0.beta) of <b>eventmachine</b> is working on Windows
72
72
  * If you deploy your RhoConnect application deploy on <b>Heroku</b>, then use new [Cedar](http://devcenter.heroku.com/articles/cedar) stack. The Bamboo stack is older than the widespread adoption of bundler,
73
73
  so on Bamboo your application is not invoked in the context of your bundle and might not works properly.
data/doc/testing.txt CHANGED
@@ -20,8 +20,8 @@ The full code listing for this product_spec is available [on github](http://gith
20
20
  From your application's root folder:
21
21
 
22
22
  :::term
23
- $ rake rhoconnect:spec
24
- [05:51:48 PM 2011-04-19] Rhoconnect Server v3.0.0 started...
23
+ $ rhoconnect spec
24
+ [05:51:48 PM 2012-04-19] Rhoconnect Server v3.2.0 started...
25
25
  Product
26
26
  it should behave like SpecHelper
27
27
  should process Product query (PENDING: No reason given)
data/doc/tutorial.txt CHANGED
@@ -10,7 +10,7 @@ Full documentation of all capabilities of RhoConnect is in the [RhoConnect Devel
10
10
 
11
11
  ## Installing the RhoConnect Dependencies
12
12
 
13
- * Install RhoConnect as described [here](/rhoconnect/install).
13
+ * Install RhoConnect [from the command line](/rhoconnect/install) or by installing [RhoMobile Suite](/rhomobile-install).
14
14
 
15
15
  * If you have a RhoConnect license that has been sent to you, you can replace the settings/license.yml file as described [here](/rhoconnect/licensing).
16
16
 
@@ -33,7 +33,7 @@ Enter the name for your RhoConnect application in Project name; in this case, "s
33
33
  :::term
34
34
  $ rhoconnect app storeserver
35
35
  $ cd storeserver
36
-
36
+
37
37
  Next, install the application's dependencies. RhoConnect applications use [bundler](http://gembundler.com/) to manage dependencies, so you can install them with:
38
38
 
39
39
  :::term
@@ -42,21 +42,21 @@ Next, install the application's dependencies. RhoConnect applications use [bundl
42
42
  **If you are running this for the first time on Mac or Linux**, you will need to install [dtach](http://dtach.sourceforge.net/):
43
43
 
44
44
  :::term
45
- $ [sudo] rake dtach:install
45
+ $ [sudo] rhoconnect dtach-install
46
46
 
47
47
  Now you can run redis and your RhoConnect app:
48
48
 
49
49
  :::term
50
- $ rake redis:start
51
- $ rake rhoconnect:start
50
+ $ rhoconnect redis-start
51
+ $ rhoconnect start
52
52
 
53
53
  If everything went well you should see:
54
54
 
55
- [07:01:15 PM 2010-05-04] Rhoconnect Server v3.0.0 started...
55
+ [01:48:15 PM 2012-08-04] Rhoconnect Server v3.3.4 started...
56
56
 
57
57
  ## Defining RhoConnect Source Adapters
58
58
 
59
- Once RhoConnect is installed we're ready to build a RhoConnect source to integrate with our backend application. To define a RhoConnect source you just need to identify a handful of operations to interact with your backend data source: login, query, sync, create, update, delete and logoff. For more information please see the [RhoConnect source adapter](/rhoconnect/source-adapters) documentation.
59
+ Once RhoConnect is installed we're ready to build a RhoConnect source to integrate with our backend application. To define a RhoConnect source you just need to identify a handful of operations to interact with your backend data source: login, query, sync, create, update, delete and logoff. For more information please see the [RhoConnect source adapter](/rhoconnect/source-adapters) documentation.
60
60
 
61
61
  ### Generating the Source Adapter from RhoStudio
62
62
 
@@ -83,7 +83,7 @@ You can open these files for editing by clicking on them in the Project Explorer
83
83
 
84
84
  ### Generating the Source Adapter from the Command Line
85
85
 
86
- From the command line, navigate to the main folder for your RhoConnect app: in this case, storeserver.
86
+ From the command line, navigate to the main folder for your RhoConnect app: in this case, storeserver.
87
87
 
88
88
  Then run the command to generate a source adapter for the product model. The product model is used as an example for a Rhodes storemanager in the [RhoStudio tutorial](/rhostudio.tutorial) and the [documentation to generate a Rhodes application](/rhodes/generator).
89
89
 
@@ -107,47 +107,47 @@ The generated source adapter file (in this case, product.rb) is similar to the c
107
107
  def initialize(source)
108
108
  super(source)
109
109
  end
110
-
110
+
111
111
  def login
112
112
  # TODO: Login to your data source here if necessary
113
113
  end
114
-
114
+
115
115
  def query
116
- # TODO: Query your backend data source and assign the records
116
+ # TODO: Query your backend data source and assign the records
117
117
  # to a nested hash structure called @result. For example:
118
- # @result = {
118
+ # @result = {
119
119
  # "1"=>{"name"=>"Acme", "industry"=>"Electronics"},
120
120
  # "2"=>{"name"=>"Best", "industry"=>"Software"}
121
121
  # }
122
122
  raise SourceAdapterException.new("Please provide some code to read records from the backend data source")
123
123
  end
124
-
124
+
125
125
  def sync
126
- # Manipulate @result before it is saved, or save it
126
+ # Manipulate @result before it is saved, or save it
127
127
  # yourself using the Rhoconnect::Store interface.
128
128
  # By default, super is called below which simply saves @result
129
129
  super
130
130
  end
131
-
131
+
132
132
  def create(create_hash)
133
133
  # TODO: Create a new record in your backend data source
134
- # If your rhodes rhom object contains image/binary data
134
+ # If your rhodes rhom object contains image/binary data
135
135
  # (has the image_uri attribute), then a blob will be provided
136
136
  raise "Please provide some code to create a single record in the backend data source using the create_hash"
137
137
  end
138
-
138
+
139
139
  def update(update_hash)
140
140
  # TODO: Update an existing record in your backend data source
141
141
  raise "Please provide some code to update a single record in the backend data source using the update_hash"
142
142
  end
143
-
143
+
144
144
  def delete(delete_hash)
145
145
  # TODO: write some code here if applicable
146
146
  # be sure to have a hash key and value for "object"
147
147
  # for now, we'll say that its OK to not have a delete operation
148
148
  # raise "Please provide some code to delete a single object in the backend application using the object_id"
149
149
  end
150
-
150
+
151
151
  def logoff
152
152
  # TODO: Logout from the data source if necessary
153
153
  end
@@ -156,44 +156,44 @@ The generated source adapter file (in this case, product.rb) is similar to the c
156
156
  The generator will also edit settings/settings.yml and add the product adapter to the sources section with some default options:
157
157
 
158
158
  :::ruby
159
- #Sources
160
- :sources:
161
- Product:
159
+ #Sources
160
+ :sources:
161
+ Product:
162
162
  :poll_interval: 300
163
163
 
164
- The next step is for you to fill in the login, query, create, update, delete and logoff methods with your own code to call a backend service.
164
+ The next step is for you to fill in the login, query, create, update, delete and logoff methods with your own code to call a backend service.
165
165
 
166
166
  ## A RhoConnect Query
167
167
 
168
- If you're doing a readonly non-authenticated source adapter, you can just write one method, query, to retrieve records as we describe here. The following is a sample query method to interact with a simple product catalog (available at http://rhostore.heroku.com) that exposes a REST interface. Note that RhoConnect can work with any protocol. This example shows JSON over HTTP with a REST interface, since that is common. The RhoConnect source adapter is Ruby code and there are ruby libraries (aka gems) that will make it easy to connect to and parse whatever you need -- the query code would just be slightly different.
168
+ If you're doing a readonly non-authenticated source adapter, you can just write one method, query, to retrieve records as we describe here. The following is a sample query method to interact with a simple product catalog (available at http://rhostore.herokuapp.com) that exposes a REST interface. Note that RhoConnect can work with any protocol. This example shows JSON over HTTP with a REST interface, since that is common. The RhoConnect source adapter is Ruby code and there are ruby libraries (aka gems) that will make it easy to connect to and parse whatever you need -- the query code would just be slightly different.
169
169
 
170
170
  For a more complete example of rewriting the source adapter methods (such as create, update, and delete), refer to the [source adapter example](/rhoconnect/source-adapters#sample-adapter) in the RhoConnect Developer Reference.
171
171
 
172
- Our sample web service for returning all products in the catalog (http://rhostore.heroku.com/products.json) returns data like this:
173
-
172
+ Our sample web service for returning all products in the catalog (http://rhostore.herokuapp.com/products.json) returns data like this:
173
+
174
174
  :::json
175
175
  [
176
176
  {
177
177
  "product": {
178
- "name": "iPhone",
179
- "brand": "Apple",
180
- "updated_at": "2010-05-11T02:04:57Z",
181
- "price": "$299.99",
182
- "quantity": "5",
183
- "id": 649,
184
- "sku": "1234",
178
+ "name": "iPhone",
179
+ "brand": "Apple",
180
+ "updated_at": "2010-05-11T02:04:57Z",
181
+ "price": "$299.99",
182
+ "quantity": "5",
183
+ "id": 649,
184
+ "sku": "1234",
185
185
  "created_at": "2010-05-11T02:04:57Z"
186
186
  }
187
- },
187
+ },
188
188
  {
189
189
  "product": {
190
- "name": "Accord",
191
- "brand": "Honda",
192
- "updated_at": "2010-05-13T22:24:48Z",
193
- "price": "$6000",
194
- "quantity": "",
195
- "id": 648,
196
- "sku": "123",
190
+ "name": "Accord",
191
+ "brand": "Honda",
192
+ "updated_at": "2010-05-13T22:24:48Z",
193
+ "price": "$6000",
194
+ "quantity": "",
195
+ "id": 648,
196
+ "sku": "123",
197
197
  "created_at": "2010-05-11T02:04:53Z"
198
198
  }
199
199
  }
@@ -213,33 +213,33 @@ For convenience, we'll add an instance variable @base which contains the base UR
213
213
 
214
214
  :::ruby
215
215
  def initialize(source)
216
- @base = 'http://rhostore.heroku.com/products'
216
+ @base = 'http://rhostore.herokuapp.com/products'
217
217
  super(source)
218
218
  end
219
219
 
220
220
  Then fill in the query method:
221
-
221
+
222
222
  :::ruby
223
223
  def query
224
224
  parsed=JSON.parse(RestClient.get("#{@base}.json").body)
225
225
 
226
226
  @result={}
227
227
  if parsed
228
- parsed.each do |item|
228
+ parsed.each do |item|
229
229
  key = item["product"]["id"].to_s
230
230
  @result[key]=item["product"]
231
231
  end
232
- end
232
+ end
233
233
  end
234
234
 
235
- **NOTE: The code above could be much more concise, but it is written to be easily readable by programmers who are unfamiliar with the Ruby language. If you are new to Ruby, you can read [Ruby from other languages](http://www.ruby-lang.org/en/documentation/ruby-from-other-languages/) for a good introduction.
235
+ **NOTE: The code above could be much more concise, but it is written to be easily readable by programmers who are unfamiliar with the Ruby language. If you are new to Ruby, you can read [Ruby from other languages](http://www.ruby-lang.org/en/documentation/ruby-from-other-languages/) for a good introduction.
236
236
  Each hash key in the inner hash represents an attribute of an individual object. All datatypes must be strings (so the hash values need to all be strings, not integers).**
237
237
 
238
238
  For example:
239
-
239
+
240
240
  :::ruby
241
241
  @result = {
242
- "1" => {
242
+ "1" => {
243
243
  "name" => "inner tube",
244
244
  "brand" => "Michelin"
245
245
  },
@@ -247,19 +247,19 @@ For example:
247
247
  "name" => "tire",
248
248
  "brand" => "Michelin"
249
249
  }
250
- }
250
+ }
251
251
 
252
252
  ## Testing Sync from the Client
253
253
 
254
254
  Make sure you are running redis. From the folder in which you app is located, run this command.
255
255
 
256
256
  :::term
257
- $ rake redis:start
258
-
257
+ $ rhoconnect redis-start
258
+
259
259
  Then start (or restart) your server:
260
-
260
+
261
261
  :::term
262
- $ rake rhoconnect:start
262
+ $ rhoconnect start
263
263
 
264
264
  **Note: The RhoConnect application must be run from the command line. It does not run from RhoStudio.**
265
265
 
@@ -280,7 +280,7 @@ Enable sync in your corresponding Rhodes app, storemanager/app/Product/product.r
280
280
  enable :sync
281
281
  end
282
282
 
283
- To get a feel for what is happening, it is helpful to watch the server log (the output of rake rhoconnect:start) in one window, and tail the client log in another window. For example, on the iPhone, display the end of the client log with:
283
+ To get a feel for what is happening, it is helpful to watch the server log (the output of `rhoconnect start`) in one window, and tail the client log in another window. For example, on the iPhone, display the end of the client log with:
284
284
 
285
285
  :::term
286
286
  $ tail -f rholog-User.txt
@@ -293,7 +293,7 @@ To sync with the RhoConnect server, the Rhodes client must log in. The Rhodes ge
293
293
  2. Login using any name & password. The generated code allows any login, but you can modify that in application.rb.
294
294
  <img src="http://rhodocs.s3.amazonaws.com/rhoconnect-tutorial/rhosimulator-login.png"/>
295
295
 
296
- 3. If login is successful, you will see a Client ID in the settings screen. The ClientID is generated the first time you log in and is stored in the client database. It serves as a unique identifier which is required for rhoconnect. (Note: this value will persist across logins, but if you reset the client database or the user re-installs the app, a new ClientID will be generated.)
296
+ 3. If login is successful, you will see a Client ID in the settings screen. The ClientID is generated the first time you log in and is stored in the client database. It serves as a unique identifier which is required for rhoconnect. (Note: this value will persist across logins, but if you reset the client database or the user re-installs the app, a new ClientID will be generated.)
297
297
  4. Sync is triggered automatically. Click on the home icon and then select "Products" and you should see the list of product records from the server.
298
298
 
299
299
  This example shows a couple of iPhone products.
@@ -303,19 +303,19 @@ This example shows a couple of iPhone products.
303
303
  ## Creating Objects with RhoConnect
304
304
 
305
305
  For your create method, the RhoConnect server will pass you a hash containing the new record, called "create_hash". For example, it might be:
306
-
306
+
307
307
  :::ruby
308
308
  {
309
309
  "name" => "Hovercraft",
310
310
  "brand" => "Acme"
311
311
  }
312
312
 
313
- The RhoConnect sources/product.rb create method will be called once for every object that has been created on the client since the last sync. Your code for create (or edit or delete) needs to use this populated array to do its work. Below is an example of a create method against the [rhostore](http://rhostore.heroku.com), which accepts an HTTP POST to perform a create action. The create method should return a unique id string for the object for it to be later modifiable by the client. If no id is returned, then you should treat the client object as read only, because it will not be able to be synchronized.
313
+ The RhoConnect sources/product.rb create method will be called once for every object that has been created on the client since the last sync. Your code for create (or edit or delete) needs to use this populated array to do its work. Below is an example of a create method against the [rhostore](http://rhostore.herokuapp.com), which accepts an HTTP POST to perform a create action. The create method should return a unique id string for the object for it to be later modifiable by the client. If no id is returned, then you should treat the client object as read only, because it will not be able to be synchronized.
314
314
 
315
315
  :::ruby
316
316
  def create(create_hash)
317
317
  result = RestClient.post(@base, :product => create_hash)
318
-
318
+
319
319
  # after create we are redirected to the new record.
320
320
  # The URL of the new record is given in the location header
321
321
  location = "#{result.headers[:location]}.json"
@@ -323,7 +323,7 @@ The RhoConnect sources/product.rb create method will be called once for every ob
323
323
  # We need to get the id of that record and return it as part of create
324
324
  # so rhoconnect can establish a link from its temporary object on the
325
325
  # client to this newly created object on the server
326
-
326
+
327
327
  new_record = RestClient.get(location).body
328
328
  JSON.parse(new_record)["product"]["id"].to_s
329
329
  end
@@ -340,18 +340,18 @@ The generated RhoConnect application code includes a file at the root of the dir
340
340
  def authenticate(username,password,session)
341
341
  true # do some interesting authentication here...
342
342
  end
343
-
343
+
344
344
  # Add hooks for application startup here
345
345
  # Don't forget to call super at the end!
346
346
  def initializer(path)
347
347
  super
348
348
  end
349
-
349
+
350
350
  # Calling super here returns rack tempfile path:
351
351
  # i.e. /var/folders/J4/J4wGJ-r6H7S313GEZ-Xx5E+++TI
352
352
  # Note: This tempfile is removed when server stops or crashes...
353
353
  # See http://rack.rubyforge.org/doc/Multipart.html for more info
354
- #
354
+ #
355
355
  # Override this by creating a copy of the file somewhere
356
356
  # and returning the path to that file (then don't call super!):
357
357
  # i.e. /mnt/myimages/soccer.png
@@ -367,7 +367,7 @@ If your back end web service requires authentication, add code to the authentica
367
367
 
368
368
  :::ruby
369
369
  def authenticate(username, password, session)
370
- # ... connect to backend using API and authenticate ...
370
+ # ... connect to backend using API and authenticate ...
371
371
  if success
372
372
  # save the data for later use in the source adapter
373
373
  Store.put_value("username:#{username}:token",username)