rhomobile / rhosync

Rhosync is a rails application to facilitate accessing information from hosted backend applications and syncing that information to mobile devices.

This URL has Read+Write access

README.rdoc

Rhosync

Rhosync is a Ruby-based framework to access data from various backend applications and sync them to remote devices. Specifically it is a Ruby on Rails application that allows managing backend application sources and user subscriptions to those data sources. It is optimized for delivery of ongoing incremental updates of those data sources to users accessing that data via mobile devices.

Design Goals

RhoSync retrieves data via web services (REST or SOAP) from backend enterprise applications for distribution to downstream mobile devices. It keeps a master store of all enterprise application data and keeps track of the information that users have received. It is written to be far simpler to be far simpler to deploy and configure than similar technologies that have come and gone over the past decade.

It is also more focused on the complete end to end ‘web service backend’ to mobile device (with an enabling master data store on the server) than earlier equivalents. These products were generally focused on the device endpoint syncing to a server-based database. With the success of Software as a Service (SaaS) products such as SugarCRM and SalesForce, synchronization directly to a server database is much more rarely a viable option. Instead we focus on the web service access scenario. Rhosync is also focused on arbitrary enterprise application data as opposed to being a PIM and email focused product such as Funambol.

SYSTEM INSTALLATION AND USAGE

PREREQUISITES

    * Ruby on Rails Version 2.1
    * mySQL, SQLite or other database that plays nicely with Rails

ADMINISTRATION

    * install the Rails application files (generally by unzipping)
    * set up the database, generally by running “rake db:migrate”

SET UP A BACKEND DATA SOURCE

    * we ship with an example "Source" out of the box for integrationg with
      SugarCRM
    * This is delivered in the Sources.yml files that should execute when you run the migrations.
       The Ruby code to interact with the backends is populated into those source records
    * Edit the “login”, “password” and “URL” fields if you are using one of the existing sources
    * Otherwise create a new Source from the application main menu and edit those same fields.
    * If you are using another backend you may need to create “prolog”, “call”,
     "createcall", "updatecall", "deletecall",  “epilog” and “sync” fields with the appropriate code. See “Creating a Rhosync Datasource”

HOW IT WORKS

Rhosync normalizes all backend application data into a common server-based database schema, in preparation for delivering the further downstream, generally to mobile devices.

Specifically the “master server data table” is a “property bag” model, which keeps track of data sources, individual objects and the name/value pairs for those objects. This allows handling of diverse backend application data structures within a single master store. It also provides for efficient delivery of single “fields” of data in either direction (e.g. just the status changing of a trouble ticket).

The connection code for logging into a backend application (via REST or SOAP APIs), calling the data retrieval and update functions, logging off, and populating the master data table are each written in Ruby but stored in the application sources table. The schema for this table and other tables involved in supporting this functionality are as described below.

DATABASE SCHEMA

There are two important tables that describe fully the universe of data sources and their contents for downstream syncing. These are the SOURCES table and the OBJECT_VALUES table (and the corresponding Source and ObjectValues models. Other tables include tables to keep of the mobile device users and their subscriptions to the various data sources available.

OBJECT_VALUES

A “property bag” schema that facilitatest importing any kind of data into a common table for later distribution to downstream clients.

    * object – the unique identifier of the object (generally an integer “record ID” from the backend system)
    * attribute – the name of the attribute (e.g. “Account Name”, “Industry”)
    * value – the value of the attribute (e.g. “Acme Corp”, “software”)
    * source_id – reference back to the source (see below) used for syncing

SOURCES

This table contains all of the information necessary to connect to a given backend system. These includes the URL to connect to and authentication information.

    * URL – the URL to connect to (for REST adapters) or the URL to the WSDL (for SOAP services)
    * SERVER – OPTIONAL a logical name for the data source server (AcmeCorpSugar)
    * LOGIN – the username or logon ID for the backend
    * PASSWORD – password (stored in the clear right now) for the backend system

Backend Code Columns

    * PROLOG – a set of Ruby code generally for logging into the backend system. Generally this is a SOAP or REST call which populates a session_id variable (that variable must be used in the call code below).
    * CALL – the actual code for getting data back (generally uses the session_id acquired in the prolog)
    * CREATECALL - code to create records in the backend from the object values table
    * UPDATECALL - update code for the backend
    * DELETECALL - record deletion code for the backend
    * LOGOUT – OPTIONAL, code to logoff the backend system
    * SYNC – this is the code used to take apart the returned data and stuff it into the OBJECT_VALUES property bag table. Theoretically this could be done in the CALL column.

SAMPLE SOURCE ADAPTER

This is a sample source adapter to retrieve Sugar Account objects.

sugar:

  id: 1
  name: RhoSugar
  url: http://rhomobile.com/sugar/soap.php?wsdl
  login: admin
  password: acc3ss$ugar
  prolog: |
    u = @source.login
    p = Digest::MD5.hexdigest(@source.password)
    ua = {'user_name' => u,'password' => p}
    ss = client.login(ua,nil)
    if ss.error.number.to_i != 0
      p 'failed to login - #{ss.error.description}'
      return
    else
      session_id = ss['id']
      uid = client.get_user_id(session_id)
    end

  call: |
    module_name = 'Accounts'
    query = '' # gets all the acounts, you can also use SQL like 'accounts.name like '%company%''
    order_by = '' # in default order. you can also use SQL like 'accounts.name'
    offset = 0
    select_fields = ['name','industry'] # this can't be an empty array
    max_results = '10000' # if set to 0 or '', this doesn't return all the results
    deleted = 0 # whether you want to retrieve deleted records, too
    result = client.get_entry_list(session_id,module_name,query,order_by,offset,select_fields,max_results,deleted);

  sync: |
    result.entry_list.each do |x|
      x.name_value_list.each do |y|
        o=ObjectValue.new
        o.source_id=@source.id
        o.object=x['id']
        o.attrib=y.name
        o.value=y.value
        o.update_type='query'
        o.save
      end
    end

  createcall:
    # name_value_list is passed in and can be used in the code below
    # for creates we just assume that the primary keys (if fields) are left out
    result=client.set_entry(session_id,'Accounts',name_value_list);
    p result.inspect.to_s

  updatecall:
    # name_value_list is passed in and can be used in the code below
    result=client.set_entry(session_id,'Accounts',name_value_list);
    p result.inspect.to_s

  deletecall:
    name_value_list.push({'name'=>'deleted','value'=>'1'});
    result=client.set_entry(session_id,'Accounts',name_value_list);
    p result.inspect.to_s

  epilog:
    client.logout(session_id)

SUPPORT

Send questions to info@rhomobile.com