doc/tutorial.txt in rhoconnect-3.3.6 vs doc/tutorial.txt in rhoconnect-3.4.2

- old
+ new

@@ -8,11 +8,11 @@ Full documentation of all capabilities of RhoConnect is in the [RhoConnect Developer Reference](/rhoconnect/introduction). ## Installing the RhoConnect Dependencies -* Install RhoConnect as described [here](/rhoconnect/install). +* Install RhoConnect [from the command line](/rhoconnect/install) or by installing [RhoMobile Suite](/rhomobile-install). * 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). Now you are ready to write your RhoConnect app. You can generate an app with RhoStudio, or with the RhoConnect app command. @@ -31,34 +31,34 @@ ### Generating a RhoConnect App from the Command Line :::term $ rhoconnect app storeserver $ cd storeserver - + Next, install the application's dependencies. RhoConnect applications use [bundler](http://gembundler.com/) to manage dependencies, so you can install them with: :::term $ [sudo] bundle install **If you are running this for the first time on Mac or Linux**, you will need to install [dtach](http://dtach.sourceforge.net/): :::term - $ [sudo] rake dtach:install + $ [sudo] rhoconnect dtach-install Now you can run redis and your RhoConnect app: :::term - $ rake redis:start - $ rake rhoconnect:start + $ rhoconnect redis-start + $ rhoconnect start If everything went well you should see: - [07:01:15 PM 2010-05-04] Rhoconnect Server v3.0.0 started... + [01:48:15 PM 2012-08-04] Rhoconnect Server v3.3.4 started... ## Defining RhoConnect Source Adapters -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. +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. ### Generating the Source Adapter from RhoStudio To generate a RhoConnect source adapter and create the associated Controller templates, right-click on the application project in the Project Explorer and select New->Rhoconnect Source Adapter. @@ -81,11 +81,11 @@ You can open these files for editing by clicking on them in the Project Explorer. ### Generating the Source Adapter from the Command Line -From the command line, navigate to the main folder for your RhoConnect app: in this case, storeserver. +From the command line, navigate to the main folder for your RhoConnect app: in this case, storeserver. 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). :::term $ rhoconnect source product @@ -105,97 +105,97 @@ :::ruby class Product < SourceAdapter def initialize(source) super(source) end - + def login # TODO: Login to your data source here if necessary end - + def query - # TODO: Query your backend data source and assign the records + # TODO: Query your backend data source and assign the records # to a nested hash structure called @result. For example: - # @result = { + # @result = { # "1"=>{"name"=>"Acme", "industry"=>"Electronics"}, # "2"=>{"name"=>"Best", "industry"=>"Software"} # } raise SourceAdapterException.new("Please provide some code to read records from the backend data source") end - + def sync - # Manipulate @result before it is saved, or save it + # Manipulate @result before it is saved, or save it # yourself using the Rhoconnect::Store interface. # By default, super is called below which simply saves @result super end - + def create(create_hash) # TODO: Create a new record in your backend data source - # If your rhodes rhom object contains image/binary data + # If your rhodes rhom object contains image/binary data # (has the image_uri attribute), then a blob will be provided raise "Please provide some code to create a single record in the backend data source using the create_hash" end - + def update(update_hash) # TODO: Update an existing record in your backend data source raise "Please provide some code to update a single record in the backend data source using the update_hash" end - + def delete(delete_hash) # TODO: write some code here if applicable # be sure to have a hash key and value for "object" # for now, we'll say that its OK to not have a delete operation # raise "Please provide some code to delete a single object in the backend application using the object_id" end - + def logoff # TODO: Logout from the data source if necessary end end The generator will also edit settings/settings.yml and add the product adapter to the sources section with some default options: :::ruby - #Sources - :sources: - Product: + #Sources + :sources: + Product: :poll_interval: 300 -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. +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. ## A RhoConnect Query -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. +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. 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. -Our sample web service for returning all products in the catalog (http://rhostore.heroku.com/products.json) returns data like this: - +Our sample web service for returning all products in the catalog (http://rhostore.herokuapp.com/products.json) returns data like this: + :::json [ { "product": { - "name": "iPhone", - "brand": "Apple", - "updated_at": "2010-05-11T02:04:57Z", - "price": "$299.99", - "quantity": "5", - "id": 649, - "sku": "1234", + "name": "iPhone", + "brand": "Apple", + "updated_at": "2010-05-11T02:04:57Z", + "price": "$299.99", + "quantity": "5", + "id": 649, + "sku": "1234", "created_at": "2010-05-11T02:04:57Z" } - }, + }, { "product": { - "name": "Accord", - "brand": "Honda", - "updated_at": "2010-05-13T22:24:48Z", - "price": "$6000", - "quantity": "", - "id": 648, - "sku": "123", + "name": "Accord", + "brand": "Honda", + "updated_at": "2010-05-13T22:24:48Z", + "price": "$6000", + "quantity": "", + "id": 648, + "sku": "123", "created_at": "2010-05-11T02:04:53Z" } } ] @@ -211,57 +211,57 @@ For convenience, we'll add an instance variable @base which contains the base URL of the web service and sets the value in the constructor: :::ruby def initialize(source) - @base = 'http://rhostore.heroku.com/products' + @base = 'http://rhostore.herokuapp.com/products' super(source) end Then fill in the query method: - + :::ruby def query parsed=JSON.parse(RestClient.get("#{@base}.json").body) @result={} if parsed - parsed.each do |item| + parsed.each do |item| key = item["product"]["id"].to_s @result[key]=item["product"] end - end + end end -**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. +**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. 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).** For example: - + :::ruby @result = { - "1" => { + "1" => { "name" => "inner tube", "brand" => "Michelin" }, "2" => { "name" => "tire", "brand" => "Michelin" } - } + } ## Testing Sync from the Client Make sure you are running redis. From the folder in which you app is located, run this command. :::term - $ rake redis:start - + $ rhoconnect redis-start + Then start (or restart) your server: - + :::term - $ rake rhoconnect:start + $ rhoconnect start **Note: The RhoConnect application must be run from the command line. It does not run from RhoStudio.** The code for the source adapter loads when the server starts. If you have a syntax error in your Ruby code, it will be reported and the server will not start; however, if you have a runtime error, that will not be reported until the source adapter is called. @@ -278,11 +278,11 @@ include Rhom::PropertyBag enable :sync end -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: +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: :::term $ tail -f rholog-User.txt To sync with the RhoConnect server, the Rhodes client must log in. The Rhodes generated app includes some screens for login and other common functions, which you will typically modify to suit the design of your application. The generated UI is useful since it allows you to focus on the core functionality of your application before implementing the important, but mundane, details of user authentication and settings. @@ -291,41 +291,41 @@ <img src="http://rhodocs.s3.amazonaws.com/rhoconnect-tutorial/storemanager-rhosimulator-home-arrows.png"/> 2. Login using any name & password. The generated code allows any login, but you can modify that in application.rb. <img src="http://rhodocs.s3.amazonaws.com/rhoconnect-tutorial/rhosimulator-login.png"/> -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.) +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.) 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. This example shows a couple of iPhone products. <img src="http://rhodocs.s3.amazonaws.com/rhoconnect-tutorial/rhosimulator-product-list.png"/> ## Creating Objects with RhoConnect For your create method, the RhoConnect server will pass you a hash containing the new record, called "create_hash". For example, it might be: - + :::ruby { "name" => "Hovercraft", "brand" => "Acme" } -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. +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. :::ruby def create(create_hash) result = RestClient.post(@base, :product => create_hash) - + # after create we are redirected to the new record. # The URL of the new record is given in the location header location = "#{result.headers[:location]}.json" # We need to get the id of that record and return it as part of create # so rhoconnect can establish a link from its temporary object on the # client to this newly created object on the server - + new_record = RestClient.get(location).body JSON.parse(new_record)["product"]["id"].to_s end You will need to restart RhoConnect to reload the source adapter after modifying code. Note that the object will be created on the client right away, but it will be sent to the server on the next sync. @@ -338,22 +338,22 @@ class Application < Rhoconnect::Base class << self def authenticate(username,password,session) true # do some interesting authentication here... end - + # Add hooks for application startup here # Don't forget to call super at the end! def initializer(path) super end - + # Calling super here returns rack tempfile path: # i.e. /var/folders/J4/J4wGJ-r6H7S313GEZ-Xx5E+++TI # Note: This tempfile is removed when server stops or crashes... # See http://rack.rubyforge.org/doc/Multipart.html for more info - # + # # Override this by creating a copy of the file somewhere # and returning the path to that file (then don't call super!): # i.e. /mnt/myimages/soccer.png def store_blob(blob) super #=> returns blob[:tempfile] @@ -365,10 +365,10 @@ If your back end web service requires authentication, add code to the authenticate method and return true if authentication was successful or false to deny access to the application from this client. For example: :::ruby def authenticate(username, password, session) - # ... connect to backend using API and authenticate ... + # ... connect to backend using API and authenticate ... if success # save the data for later use in the source adapter Store.put_value("username:#{username}:token",username) end return success \ No newline at end of file