Last active
March 31, 2016 00:54
-
-
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.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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