Rhom Ruby API

Allows Ruby access to the Rhodes mini database object mapper, performing database operation on Rhodes model objects.

For JavaScript access to the Rhom, see the ORM JavaScript API.

can_modify

Returns true if the Rhodes model object is not currently being synced (if it is being synced, you should disable editing of the object).

Before displaying an edit page for an object, your application can check if the object is currently being accessed by the sync process. If it is, you should disable editing of the object. can_modify could return true, for example, on a new local record that was created and sent to the RhoConnect application, but no response has been received yet.

modelname.can_modify

Example

Before displaying an edit page for an object, your application can check if the object is currently being accessed by the sync process. If it is, you should disable editing of the object. can_modify could return true, for example, on a new local record that was created and sent to the RhoConnect application, but no response has been received yet.

def edit
  @product = Product.find(@params['id'])
  if @product && !@product.can_modify
    render :action => :show_edit_error
  else    
    render :action => :edit
  end
end

changed?

Returns true if a Rhodes model object has local database changes that need to be synchronized, false otherwise.

modelname.changed?

Example

Determine if a rhom model has local database changes that need to be synchronized.

def should_sync_product_object
  if Product.changed?
    #... do stuff ...
  end
end

client_id

Returns the current sync client id.

modelname.client_id

clear_notification

Clear notification for the object.

modelname.clear_notification

count

Returns the number of objects in the named model. This is equivalent to using the modelname.find() method with the :count argument.

modelname.count

create

Create a new Rhodes model object and save it to the database.

This is the fastest way to insert a single item into the database.

modelname.create(attributes)
attributes List of attributes assigned to the new model object, such as {"name" => "ABC Inc.","address" => "555 5th St."}.

Example

Create a new rhom object and save to the database.

@account = Account.create(
  {"name" => "some new record", "industry" => "electronics"}
)

database_export

Creates a zip archive of a local database partition with all its blob objects, and returns a path to that zip archive.

Rhom::Rhom.database_export(partition)
partition a local database partition.

database_fullclient_reset_and_logout

Reset the Rhodes model database and logout. Equivalent to Rhom::Rhom.database_full_reset(true) followed by SyncEngine.logout.

If you receive a sync error “Unknown client” message in your sync callback, this means that the RhoConnect server no longer knows about the client and a Rhom::Rhom.database_fullclient_reset_and_logout is recommended. This error requires proper intervention in your app so you can handle the state before resetting the client. For example, your sync notification could contain the following:

if @params['error_message'].downcase == 'unknown client'
  puts "Received unknown client, resetting!"
  Rhom::Rhom.database_fullclient_reset_and_logout
end

database_full_reset

Deletes all records from the property bag and model tables.

Rhom::Rhom.database_full_reset(reset_client_info, reset_local_models)
reset_client_info true to clean the client_info table, false otherwise.
reset_local_models true to clean local (non-synced) models, false otherwise.

database_full_reset_and_logout

Perform a full reset, then logout the RhoConnect client.

Rhom::Rhom.database_full_reset_and_logout

database_import

Imports the database and blob objects from a zip archive created with database_export. If the imported archive is inconsistent, or other failure occurs during the import process, the original database will be restored.

Rhom::Rhom.database_import(partition, path_to_zip)
partition the local database partition to be replaced by the zip.
path_to_zip path to the zip archive created with database_export.

database_local_reset

Reset only local (non-sync-enabled) models.

Rhom::Rhom.database_local_reset

delete_all

Delete all Rhodes model objects for a source, filtering by conditions.

modelname.delete_all(:conditions, :op)
:conditions (optional) hash of attribute/values; delete only objects matching these criteria, such as :conditions => {'industry'=>'electronics'}.
:op (optional) operator, such as "OR" or "IN". Allows you to have more than one set of conditions.

destroy

Destroy a Rhodes model object.

modelname.destroy

Examples

Deletes all rhom objects for a source, optionally filtering by conditions:

# :conditions   Delete only objects matching these criteria. 
#               Supports find() conditions.
# :op           See advanced find syntax
Account.delete_all(:conditions => {'industry'=>'electronics'})

Delete a rhom object.

@account = Account.find(:all).first
@account.destroy

find

Find Rhodes model objects.

modelname.find(argument list)

The argument list can consist of the following arguments.

:all returns all objects; can use optional :conditions.
:first returns first object matching :conditions.
:count returns the number of objects matching these :conditions.
:conditions (optional) hash of attribute/values. Also supports sql fragments (i.e. "name like 'rhomobile'") or sql fragment with binding (you have to define :select with sql queries) (i.e. ["name like ?", "'#{company#}'"]) Use a comma around string values.
:order (optional) attribute(s) to order the list.
:orderdir (optional) Order direction: 'ASC' ascending, 'DESC' descending. Default = 'ASC'.)
:select (optional) array of string attributes to return with the object. Useful if your model has many attributes and your query only needs a few of them.
:per_page (optional) maximum number of items to return.
:offset (optional) offset from beginning of the list.
:op (optional) operator, such as "OR" or "IN". Allows you to have more than one set of conditions.

Examples

Find Rhom objects.. Also see Advanced queries

acct = Account.find "3560c0a0-ef58-2f40-68a5-48f39f63741b"

acct.name 
  #=> "A.G. Parr PLC 37862"

accts = Account.find(:all, :select => ['name','address'])

accts[0].name 
  #=> "A.G. Parr PLC 37862"

accts[0].telephone 
  #=> nil

Use SQL fragments with caution. They are considerably slower than advanced queries described below. You also have to specify :select parameter.

Order Examples

The :order argument for find accepts several forms.

:order by one attribute.

        @accts = Account.find(
      :all, 
      :order => 'name',
      :orderdir => 'DESC'
    )

:order by one attribute with a block.

        @accts = Account.find(:all, :order => 'name') do |x,y|
      y <=> x    
    end

:order with a block.

        @accts = Account.find(:all) do |item1,item2|
      item2.name <=> item1.name
    end

:order by multiple attributes.

        @accts = Account.find(
      :all, 
      :order => ['name', 'industry'], 
      :orderdir => ['ASC', 'DESC']
    )

find_by_sql(sql_query) returns rhom object(s) based on sql_query. This method works only for schema models.

@accts = Account.find_by_sql("SELECT * FROM Account")

find_all

Alias for modelname.find(:all, argument list).

find_by_sql

Returns Rhodes model object(s) based on sql_query. This method works only for schema models.

modelname.find_by_sql(sql_query)
sql_query An sql query, such as "SELECT * FROM Account".

get_source_id

Returns the source id number for this Rhodes model object.

modelname.get_source_id

get_source_name

Returns the source name for this Rhodes model object.

modelname.get_source_name

metadata

Returns the metadata definition for a given model as a hash.

Product.metadata
#=> {'foo' => 'bar'}

Example

Returns the metadata for a given model.

Product.metadata
#=> {'foo' => 'bar'}

Assigns the metadata for a given model.

Product.metadata = { 'foo' => 'bar' }.to_json

metadata=(metadata_def)

Assigns the JSON metadata definition for a given model.

Product.metadata = { 'foo' => 'bar' }.to_json
metadata_def JSON string of the metadata definition

new

Create a new Rhodes model object.

modelname.new(attributes)
attributes List of attributes assigned to the new model object, such as {"name" => "ABC Inc.","address" => "555 5th St."}.

Example

Create a new rhom object and assign given attributes.

@account = Account.new(
  {"name" => "ABC Inc.","address" => "555 5th St."}
)
@account.name 
  #=> "ABC Inc."

paginate

Call find with a limit on the number of records. Default page size is 10.

modelname.paginate(*arguments)

The *arguments you can use are:

:page which page to return.
:per_page with :page (used as offset), the number of records to return, such as :page => 1, :per_page => 20
:conditions same as find with :conditions
:order same as find with :order
:select same as find with :select

Example

Paginate calls find with a limit on the # of records. This emulates rails' classic pagination syntax. Default page size is 10.

Account.paginate(:page => 0) 
  #=> returns first 10 records
Account.paginate(:page => 1, :per_page => 20) 
  #=> returns records 21-40
Account.paginate(
  :page => 5, 
  :conditions => {'industry' => 'Technology'}, 
  :order => 'name'
) #=> you can have :conditions and :order as well

push_changes

Force the sending of local changes to the RhoConnect server.

This method is available in Ruby only.
modelname.push_changes()

This method can be used even when there are no pending changes, to artificially put the client into a state where it sends a POST request to the server on the next sync (even if it is an empty sync). An empty POST method is useful because if there is something left in the CRUD queue in the server, it will be forced to be processed. For example:

  1. Five records are created on the client.
  2. 1st sync, five records are sent to RhoConnect, all of those records are marked as sent on the client.
  3. RhoConnect starts processing the records on the server and 3rd record is thrown out (for some reason) by the back-end.
  4. RhoConnect sends 1st & 2nd record as processed and also sends create-error with 3rd record and PUSHES remaining records, 4th & 5th, back into the server queue.
  5. After that, if you choose to use the :delete action, there are no more pending changes on the client. The 4th & 5th records were sent and no error was received, so the client assumes it will receive the records later, maybe as a postponed job.
  6. So, if you just trigger Sync now on the client, the 4th & 5th records won’t be processed on server still because, in order to process the queue there should be a POST method and Sync will send POST method only if there are new changes and, as it stands, there are none.
  7. So, to force the server to process the remainder of the queue, you can use the push_changes method. This will force a POST method to be sent in the next sync (even if there are no changes) and will, in turn, force queue to be processed on the server.

sync

Start the sync process for a Rhodes model.

modelname.sync(callback_url, callback_data, show_status_popup, query_params)
callback_url the url for the sync callback method. If this is used, SyncEngine.set_notification is called before SyncEngine.dosync.
callback_data Data for the callback method.
show_status_popup true if you want to show a popup window upon sync, false otherwise.
query_params Optional. a query to pass to the sync server. The query_params value must be URL encoded.

Example

Start the sync process for a model. In this example, the value for @params[“sku”] — the value of the sku — must be URL encoded.

Product.sync( url_for(:action => :sync_callback), "", false, "query=#{@params["sku"]}" )

Set a notification to be called when the sync is complete for this model. This is useful for example if you want to refresh the current list page or display an alert when new data is synchronized. See the sync notification docs for more information.

Account.set_notification( url_for(:action => :sync_notify), "")

save

Saves the current Rhodes model object to the database.

modelname.save

set_notification

Set a notification to be called when the sync is complete for this model.

modelname.set_notification(callback_url, params)
callback_url the url for your sync is finished notification callback method.
params parameters for the callback method.

update_attributes

Updates the current Rho model object attributes and saves it to the database. This is the fastest way to add or update model attributes.

modelname.update_attributes(attributes)
attributes List of attributes and their updated values, such as {"name" => "ABC Inc.","address" => "555 5th St."}.

Example

Update the current rhom object’s attributes and saves it to the database.

This is the fastest way to add or update item attributes.

@account = Account.find(
  :all, 
  :conditions => {'name' => 'ABC Inc.'}
)
@account.update_attributes(
  {"name" => "ABC Inc.", "industry" => "Technology"}
)
@account.industry   
  #=> "Technology"

Saves the current rhom object to the database.

@account = Account.new(
  {"name" => "some new record", "industry" => "electronics"}
)
@account.save

Advanced Queries

find(*args) (advanced conditions)

Rhom also supports advanced find :conditions. Using advanced :conditions, rhom can optimize the query for the property bag table.

Let’s say we have the following SQL fragment condition:

Product.find(
 :all, 
 :conditions => [ 
   "LOWER(description) like ? or LOWER(title) like ?", 
   query, 
   query
 ], 
 :select => ['title','description'] 
)

Using advanced :conditions, this becomes:

Product.find( 
  :all, 
  :conditions => { 
    { 
      :func => 'LOWER', 
      :name => 'description', 
      :op => 'LIKE'
    } => query, 
    {
      :func => 'LOWER', 
      :name => 'title', 
      :op => 'LIKE'
    } => query
  }, 
  :op => 'OR', 
  :select => ['title','description']
)

You can also use the ‘IN’ operator:

Product.find(
  :all, 
  :conditions => { 
    {
      :name => "image_uri", 
      :op => "IN" 
    } => "'15704','15386'" 
  } 
)

# or use array notation
Product.find(
  :all, 
  :conditions => { 
    {
      :name => "image_uri", 
      :op => "IN" 
    } => ["15704","15386"]
  } 
)

You can also group :conditions:

cond1 = {
  :conditions => { 
    {
      :func => 'UPPER', 
      :name => 'name', 
      :op => 'LIKE' 
    } => query, 
    { 
      :func => 'UPPER', 
      :name => 'industry', 
      :op => 'LIKE'
    } => query
  }, 
  :op => 'OR'
}

cond2 = {
  :conditions => { 
    {
      :name => 'description', 
      :op => 'LIKE'
    } => 'Hello%'
  }   
}

@accts = Account.find( 
  :all, 
  :conditions => [cond1, cond2], 
  :op => 'AND', 
  :select => ['name','industry','description']
)

Find by numeric field

To use number comparison conditions in find use CAST :

@accts = Account.find(:all, 
    :conditions => { {:func=> 'CAST', :name=>'rating as INTEGER', :op=>'<'} => 3 } )
#or using sql query:
size = 3
@accts = Account.find(:all, 
    :conditions => ["CAST(rating as INTEGER)< ?", "#{size}"], :select => ['rating'] )