Skip to content
Find file
Fetching contributors…
Cannot retrieve contributors at this time
185 lines (140 sloc) 6.09 KB

Rest In Motion

RestKit's object mapping functionality is broken in Ruby Motion. Rest In Motion is a thin layer overtop of the working component of RestKit (RKClient), that reimplements object mapping in ruby. It also restyles the way regular request are done.


First you should initialize the "request god" in your application's delegate in the application:didFinishLaunchingWithOptions: method and save it to an app delegate instance variable so that it never leaves memory. You should initialize it with ".instance" and pass it the base URL of the server you're going to communicate with (don't add a trailing slash to the URL):

class AppDelegate
  attr_accessor :request_god

  def application(application, didFinishLaunchingWithOptions:launchOptions)
    @request_god = RequestGod.instance ""

    @window = UIWindow.alloc.initWithFrame UIScreen.mainScreen.bounds
    @window.rootViewController = RegularRequestViewController.alloc.init
    @window.rootViewController.wantsFullScreenLayout = true

Now you can use the request god in you view controller's to make simple HTTP Get, Post, Put, and Delete requests, like so:

class RegularRequestExampleViewController < UIViewController
  attr_accessor :login_request_id

  def init

  def driver

    # use .instance to get ahold of the request god you initialized in your app delegate
    request_god = RequestGod.instance

    # use .RegularRequest to spawn a simple HTTP Get, Post, etc. Pass in the resource path, method, and callback delegate
    login_request = request_god.RegularRequest('/tokens.json', method:POST, delegate:self)

    # optionally, you can add post/put parameters
    login_request.params = { "email" => "", "password" => "password" }

    # optionally, you can set a specific callback for when the request results return; more on this later
    # login_request.callback = :"login_response:"

    # save the request ID
    @login_request_id =

    # send the request

  # called only if you assigned login_request.callback
  def login_response(response)
    puts "response to login request: #{response.str}"

  # called if no login_request.callback was assigned
  def received(response, id:id)
    puts "response to login request: #{response.str}" if id == @login_request_id

The default callback for all requests is

received(response, id:id)

If you use this, save the ID's of all the requests you create (when you create them) so that you know which request you're receiving the resposne for. Optionally, you can set the

login_request.callback = :"some_method_with_one_parameter:"

If you do this, the result of the login_request will not trigger the received: id: method, but the specified one instead. And it will not pass in the request id because you already know which request's response you're parsing because you're in its unique callback function.

Object Mapping Example

class ResourceRequestViewController < UIViewController
  attr_accessor :game_mapping, :team_mapping

  def init

  def driver
    request_god = RequestGod.instance
    games_request = request_god.ResourceRequest('/castle/seasons/4/games.json?auth_token=tok', method:GET, delegate:self)

    # use mappings hash to map { json_key => object_var_name }
    @game_mapping =
    @game_mapping.mappings = { "league_id" => "league_id", "season_id" => "season_id", "rounds_count" => "num_rounds", "home_team" => "home_team" }

    # use sub_mappings hash to map { object_var_name => object_mapping }
    @team_mapping =
    @team_mapping.mappings = { "url" => "url", "id" => "id", "name" => "name" }
    @game_mapping.sub_mappings = { "home_team" => @team_mapping }

    games_request.root_mapping = game_mapping
    games_request.callback = :"games:"

  def games(games)
    games.each { |game| puts "#{game}" } # automatically unserialized and mapped to an array of game ojects

    # to reserialize the games into json:
    # games.each { |game| puts "#{@game_mapping.serialize(game)}" }

Hopefully this is clear. Note that for this code to work you should have a Game class defined somewhere in your project with member variables: league_id, season_id, num_rounds, and home_team. You should also have a Team class defined somewhere with member variables: url, id, and name.


To install this, install cocoapods:

gem install cocoapods
pod setup

And I like to be able to search for pods from the command line. If you would too (though not necessary), add:

brew install appledoc --HEAD
ln -sf "`brew --prefix`/Cellar/appledoc/HEAD/Templates" ~/Library/Application\ Support/appledoc

Now install motion-cocoapods

gem install motion-cocoapods

Now add these two lines under the existing require in your rakefile:

    require 'rubygems'
    require 'motion-cocoapods'

And add these lines:

    Motion::Project::App.setup do |app|
      # stuff
      app.pods do
        dependency 'RestKit/Network'
        dependency 'RestKit/UI'
        dependency 'RestKit/Testing'
        dependency 'RestKit/ObjectMapping'
        dependency 'RestKit/ObjectMapping/CoreData'

Finally, from within your projects root directory (assuming you've initialized a git repo here) do:

git submodule add ./app/rim

You should also modify your .gitignore to ignore the restkit build files so you're not pushing and pulling an extra library every time you make a commit. Add this line to your .gitignore:


On a side note, if you push your project to your own repo and then pull it later on, you will have to reinitialize Rest In Motion like so:

git pull git://yourrepohere.git
cd ./yourrepohere
git submodule init
git submodule update

That should be all! I hope this is helpful!

Something went wrong with that request. Please try again.