Skip to content
master
Go to file
Code

Latest commit

 

Git stats

Files

Permalink
Failed to load latest commit information.
Type
Name
Latest commit message
Commit time
app
 
 
lib
 
 
 
 
 
 
 
 
 
 
 
 
 
 

README.md

Deprecation Warning

remote_model is from a time and place in RubyMotion where only the hackiest of hacks made this possible; please look into using (the tentatively titled) Maglev as a more modern, stable replacement:

https://github.com/clayallsopp/maglev

RemoteModel

JSON API <-> NSObject in one line. Powered by RubyMotion and BubbleWrap.

Example

Let's say we have some User and Question objects retrievable via our API. We can do fun stuff like:

# GET http://ourapi.com/users/1.json -> {:user => {id: 1}}
user = User.find(1) do |user|
  # async
  # GET http://ourapi.com/users/1/questions.json -> {:questions => [...]}
  Question.find_all(user_id: user.id) do |questions|
    # async
    puts questions
  end
end

# Later...
=> [#<Question @user=#<User>, 
    #<Question @user=#<User>]

Here's what our files look like:

./app/models/user

class User < RemoteModule::RemoteModel
  attr_accessor :id

  has_many :questions

  collection_url "users"
  member_url "users/:id"
end

./app/models/question.rb

class Question < RemoteModule::RemoteModel
  attr_accessor :id, :question, :is_active

  belongs_to :user

  collection_url "users/:user_id/questions"
  member_url "users/:user_id/questions/:id"

  custom_urls :active_url => member_url + "/make_active"

  # The urls substitute params based on a passed hash and/or object's methods,
  # so we define user_id to use for the collection/member urls
  def user_id
    user && user.id
  end

  # An example of how we can use custom URLs to make custom nice(r) methods
  # EX
  # a_question.make_active(false) do |question|
  #   p question.is_active
  # end
  def make_active(active)
    post(self.active_url, payload: {active: active}) do |response, json|
      self.is_active = json[:question][:is_active]
      if block_given?
        yield self
      end
    end
  end
end

Installation

gem install remote_model

And now in your Rakefile, require remote_model:

$:.unshift("/Library/RubyMotion/lib")
require 'motion/project'
require 'remote_model'

Motion::Project::App.setup do |app|
  ...
end

Setup

Add an initialization file somewhere, like ./app/initializers/remote_model.rb. This is where we put the API specifications:

module RemoteModule
  class RemoteModel
    # The default URL for our requests.
    # Overrideable per model subclass
    self.root_url = "http://localhost:5000/"

    # Options attached to every request
    # Appendable per model subclass
    # See BubbleWrap docs on what can be passed in BubbleWrap::HTTP.<method>(url, options)
    self.default_url_options = {
        :headers => {
          "x-api-token" => "some_token",
          "Accept" => "application/json"
        }
      }
  end
end

How?

RemoteModel is designed for JSON APIs which return structures with "nice" properties.

When you make a request with a RemoteModel (self.get/put/post/delete), the result is always parsed as JSON. The ActiveRecord-esque methods take this JSON and create objects out of it. It's clever and creates the proper associations (belongs_to/has_one/has_many) within the objects, as defined in the models.

FormatableString

The AR methods also use the member/collection defined URLs to make requests. These URLs are a string which you can use :symbols to input dynamic values. These strings can be formatted using a hash and/or using an object (it will look to see if the object responds to these symbols and call the method if applicable):

>> s = RemoteModule::FormatableString.new("url/:param")
=> "url/:param"
>> s.format({param: 6})
=> "url/6"
>> obj = Struct.new("Paramer", :param).new(param: 100)
=> ...
>> s.format({}, obj)
=>  "url/100"

RemoteModels can define custom urls and call those as methods (see question.rb above).

Todo

  • More tests
  • CoreData integration

About

JSON API <-> NSObject via RubyMotion

Resources

Languages

You can’t perform that action at this time.