Skip to content

ZhangHanDong/rhosync

Repository files navigation

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.2.2
* mySQL, SQLite or other database that plays nicely with Rails

INSTALLATION & ADMINISTRATION

sudo gem install rspec rspec-rails
git clone git://github.com/rhomobile/rhosync.git
cd rhosync

Then run the db:bootstrap rake task provided, creating the database and associated tables that RhoSync needs. It will also load the source adapters that we ship with.

rake db:bootstrap

Install any required gems

sudo rake gems:install

Then use your Rails server of choice to run the application. For example:

mongrel_rails start

Then you can view the Sources from your web browser:

http://localhost:3000

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
      [email protected]
      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 [email protected]

About

No description, website, or topics provided.

Resources

License

Stars

Watchers

Forks

Packages

No packages published