class SK::SDK::Sync

Provide methods for mapping and syncing the fields of a remote to local object. Sync needs a local(left), a remote(right) object and a field-map(Array) to map the field-names between those two. Optionally you can add transition methods to convert the values from on side to the other.

When syncing the corresponding fields, the names are simply send to each object.

After an object was updated you can check the log for changes. Sync does not save anything, it only sets the field values on the other object.

Example

map =[
 [:name, :full_name, :'someClass.set_local_name', :'MyClass.set_remote_name'],
 [:street, :address1]
]
map = SK::SDK::Sync.new(@local_user, @remote_user, map)
map.update(:r)

Mapping Explained

Mappings are passed as an array:

[
 [:local_field_name, :remote_field_name, "MyClass.local_trans", "MyClass.remote_trans"]
 [:firstname, :first_name, :'MyClass.set_local_name', :'MyClass.set_remote_name']
]

A mapping consist of a local and the remote field(method) name. And might contain transition methods, if the value needs to be changed when set from one side to the other. Those methods will be called with the value from the other side.

local_obj.field = MyClass.local_trans(remote_obj.field)

Attributes

fields[R]

@return [Array<Field>] mapped fields

l_obj[RW]

@return [Object] The local object

log[R]

@return [Array<String>] log of field changes

outdated[R]

@return [Array<Field>] outdated fields

r_obj[RW]

@return [Object] The remote object

Public Class Methods

new(local_object, remote_object, field_map) click to toggle source

@param [Object] local_object @param [Object] remote_object @param [Array<String,Symbol>] field_map assign local to remote field names

# File lib/sk_sdk/sync.rb, line 54
def initialize(local_object, remote_object, field_map)
  @l_obj = local_object
  @r_obj = remote_object
  self.fields = field_map
  @log = []
end

Public Instance Methods

field(l_name) click to toggle source

Find a field by its local name

@param [Symbol] l_name local name @return [Field]

# File lib/sk_sdk/sync.rb, line 73
def field(l_name)
  fields.find{|fld| fld.l_name == l_name}
end
fields=(field_maps) click to toggle source

Create field for given mapping arrays and resets all existing ones @param [Array<Array>] field_maps

# File lib/sk_sdk/sync.rb, line 63
def fields=(field_maps)
  @fields = []
  field_maps.each { |fld| @fields << Field.new(fld) }
  @fields
end
outdated?() click to toggle source

Check if the any of the fields are outdated Populates outdated with local field names

@return [Boolean] false if not outdated

# File lib/sk_sdk/sync.rb, line 81
def outdated?
  @outdated = []
  fields.each do |fld|
    if fld.transition?
      # call r_trans method with local val to compare local with remote val
      # SomeTrans.remote_transfer_method( l_obj.field )
      virtual_l_val = eval "#{fld.r_trans} l_obj.send( fld.l_name )"
      @outdated << fld if virtual_l_val != r_obj.send( fld.r_name )
    else
      # no transfer method, directly compare values
      @outdated << fld if r_obj.send( fld.r_name ) != l_obj.send( fld.l_name )
    end
  end
  !@outdated.empty?
end
update(side, flds=nil) click to toggle source

Update a side with the values from the other side. Populates the log with updated fields and values.

@param [String|Symbol] side to update l OR r @param [Array<Field>, nil] flds fields to update, default nil update all fields

# File lib/sk_sdk/sync.rb, line 111
def update(side, flds=nil)
  raise ArgumentError, 'The side to update must be :l or :r' unless [:l, :r].include?(side)
  target, source = (side==:l) ? [:l, :r] : [:r, :l]
  # use set field/s or update all
  flds ||= fields
  target_obj = self.send("#{target}_obj")
  source_obj = self.send("#{source}_obj")
  flds.each do |fld|
    target_name = fld.send("#{target}_name")
    source_name = fld.send("#{source}_name")
    # remember for log
    old_val = target_obj.send(target_name) rescue 'empty'
    # get new value through transfer method or direct
    new_val = if fld.transition?
                cur_trans = fld.send("#{target}_trans")
                eval "#{cur_trans} source_obj.send( source_name )"
              else
                source_obj.send( source_name )
              end
    target_obj.send( "#{target_name}=" , new_val )

    log << "#{target_name} was: #{old_val} updated from: #{source_name} with value: #{new_val}"
  end
end
update_local_outdated() click to toggle source

update all local outdated fields with values from remote object

# File lib/sk_sdk/sync.rb, line 98
def update_local_outdated
  update(:l, @outdated) if outdated?
end
update_remote_outdated() click to toggle source

update all remote outdated fields with values from local object

# File lib/sk_sdk/sync.rb, line 102
def update_remote_outdated
  update( :r, @outdated) if outdated?
end