Skip to content

Instantly share code, notes, and snippets.

@stefanvermaas
Last active March 31, 2016 00:54
Show Gist options
  • Save stefanvermaas/6996822 to your computer and use it in GitHub Desktop.
Save stefanvermaas/6996822 to your computer and use it in GitHub Desktop.
To synchronize data between a RubyMotion app and a Rails API I needed a sort of a synchronization helper. This code is a proof of concept for this synchronization helper. It uses RubyMotion and BubbleWrap.
class AppDelegate
def application(application, didFinishLaunchingWithOptions:launchOptions)
# For unit testing the application
return true if RUBYMOTION_ENV == 'test'
# Get the frame for the window
@window = UIWindow.alloc.initWithFrame(UIScreen.mainScreen.bounds)
# Load all the data from the API
@sync = syncDataOnStartUp()
# This makes the window a receiver of events (for now we are using touch).
@window.makeKeyAndVisible
# Return true to start the application
true
end
def syncDataOnStartUp
# Create the new syncer class
@syncer = Syncer.new
@syncer.fetch( "all" ) # Sync all the data
end
end
class Syncer
attr_reader :all_models, :api_url
attr_accessor :model
def initialize( model = false )
@all_models = ["tasks", "clients"] # Models we have to sync when using "all"
@api_url = "http://localhost:3000/api" # API url
# Define the model if it's defined
if model
@model = toModel( model )
@collection = toCollection( model )
end
end
def fetch( model )
# Check or all models has to be fetched or just a single model
if model == 'all'
self.fetchAll
return
end
# Set the model and collection
@model = toModel( model )
@collection = toCollection( model )
# Fetch the model
BW::HTTP.get("#{@api_url}/#{@collection}") do |res|
if res.ok?
parsedData = BW::JSON.parse( res.body.to_s )
self.sync( model, parsedData )
end
end
end
def fetchAll
@all_models.each { |model| self.fetch(model) }
end
# Read out a model
def read( id, remote = false )
item = if remote
BW::HTTP.get("#{@api_url}/#{@collection}/#{id}") do |res|
if res.ok?
BW::JSON.parse( res.body.to_s )
end
end
else
@model.where(:id).eq( id ).first
end
end
# Create a new model
def create( data, remote = false )
item = if remote
BW::HTTP.post("#{@api_url}/#{@collection}", { payload: { _json: data } }) do |res|
if res.ok?
BW::JSON.parse( res.body.to_s )
end
end
else
@model.create( data )
end
end
# Update an existing model
def update( data, remote = false )
item = if remote
BW::HTTP.put("#{@api_url}/#{@collection}/#{data.id}", { payload: { _json: data.attributes } }) do |res|
if res.ok?
BW::JSON.parse( res.body.to_s )
end
end
else
@model.where(:id).eq(data.id).first.update_attributes(data)
end
end
# Delete an existing model
def delete( id, remote = false )
item = if remote
BW::HTTP.delete("#{@api_url}/#{@collection}/#{id}") do |res|
if res.ok?
BW::JSON.parse( res.body.to_s )
end
end
else
@model.where(:id).eq(id).first.delete
end
end
# - Protected methods ---------------------------------------------------- #
protected
# Sync the model
def sync( model, remoteData )
# Stop when we don't have an array
return unless remoteData.kind_of?(Array)
# Compare the remote data with the local data
for remoteItem in remoteData do
localItem = self.read( remoteItem[:id] )
# Do all the checks on the remote and local data
self.create( remoteItem ) if !localItem # Create the new data
self.update( localItem ) if localItem && localItem.updated_at < remoteItem[:updated_at] # Update the local data
self.update( remoteItem, true ) if localItem && localItem.updated_at > remoteItem[:updated_at] # Update the remote data
end
end
# - Helper functions ---------------------------------------------------- #
# Make sure a variable is a model
def toModel( model )
model = model.kind_of?(String) ? model.singularize.camelize.constantize : model
end
# Make sure we have an collection
def toCollection( model )
model = model.kind_of?(Class) ? model.to_s.singularize.pluralize.downcase : model
end
# Show a simple error message
def showErrorMessage( text )
p "ERROR: #{text}"
end
# Show a simple log message
def showLogMessage( text )
p "LOG: #{text}"
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment