motion_model_resource 0.1.6

Sign up to get free protection for your applications and to get access to all the features.
data/.gitignore ADDED
@@ -0,0 +1,11 @@
1
+ .repl_history
2
+ build
3
+ resources/*.nib
4
+ resources/*.momd
5
+ resources/*.storyboardc
6
+ .DS_Store
7
+ doc/**/*.*
8
+ doc
9
+ *.gem
10
+
11
+ .rvmrc
data/CHANGELOG ADDED
File without changes
data/Gemfile ADDED
@@ -0,0 +1,7 @@
1
+ source "https://rubygems.org"
2
+
3
+ gem "rake"
4
+ gem 'motion_model'
5
+ gem 'webstub'
6
+ gem 'bubble-wrap'
7
+ gem 'motion-support'
data/Gemfile.lock ADDED
@@ -0,0 +1,22 @@
1
+ GEM
2
+ remote: https://rubygems.org/
3
+ specs:
4
+ bubble-wrap (1.3.0.osx)
5
+ motion-require (0.0.6)
6
+ motion-support (0.2.4)
7
+ motion-require (>= 0.0.6)
8
+ motion_model (0.4.4)
9
+ bubble-wrap (= 1.3.0.osx)
10
+ motion-support (>= 0.1.0)
11
+ rake (10.0.4)
12
+ webstub (0.3.7)
13
+
14
+ PLATFORMS
15
+ ruby
16
+
17
+ DEPENDENCIES
18
+ bubble-wrap
19
+ motion-support
20
+ motion_model
21
+ rake
22
+ webstub
data/LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2013 Torben Toepper
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,152 @@
1
+ MotionModelResource: Simple JSON API Wrapper for MotionModel on RubyMotion
2
+ ==========================================================================
3
+
4
+ MotionModelResource is a simple wrapper to store your remote data in MotionModel objects. It is good for users who have a
5
+ REST API and want to have it in an iOS app.
6
+
7
+ You need to have MotionModel ready, if you want to use this implementation: https://github.com/sxross/MotionModel
8
+
9
+
10
+ ### Overview
11
+ * [Installation](#installation)
12
+ * [Setup](#setup)
13
+ * [Usage](#usage)
14
+
15
+
16
+ Installation
17
+ ------------
18
+ Add the following line to your `Gemfile`:
19
+
20
+ `gem "motion-model-resource"`
21
+
22
+ You need to require the Gem. Insert the
23
+ following immediately before `Motion::Project::App.setup`:
24
+
25
+ ```ruby
26
+ require 'motion_model' # If you haven't already
27
+ require 'motion_model_resource'
28
+ ```
29
+
30
+ Then, update your bundle:
31
+
32
+ `bundle`
33
+
34
+
35
+ Setup
36
+ -----
37
+
38
+ First of all you will need a normal MotionModel::Model:
39
+
40
+ ```ruby
41
+ class Task
42
+ include MotionModel::Model
43
+ include MotionModel::ArrayModelAdapter
44
+
45
+ columns name: :string,
46
+ long_name: :string,
47
+ due_date: :date,
48
+ lastSyncedAt: :time
49
+ end
50
+ ```
51
+
52
+ Tune this up, by adding:
53
+ ```ruby
54
+ ...
55
+ include MotionModelResource::ApiWrapper
56
+
57
+ def self.url
58
+ "https://example.com/tasks"
59
+ end
60
+
61
+ def self.wrapper
62
+ @wrapper ||= {
63
+ fields: {
64
+ id: :id,
65
+ name: :name,
66
+ long_name: :long_name,
67
+ due_date: :due_date
68
+ },
69
+ relations: [:user]
70
+ }
71
+ end
72
+ ...
73
+ ```
74
+ The wrapper hash has two main keys. The first one is "fields". Here you specify the local and remote keys, you want to have from your API response. The hash-key is the remote key and the hash-value is the local key. It is used, if you have different names in your implementation (maybe camelcase with underscore).
75
+ The second key in the main hash is the "relations" part. Here you can specify the wanted relations from your remote response. It will automatacally look after the right relation, for example if you have a relation "tasks", and the response is an array, it will create a bunch of tasks for you.
76
+
77
+ The url method will be used for saving a remote model. Maybe in future for a routes prefix.
78
+
79
+
80
+ Usage
81
+ -----
82
+
83
+ ### Getting Remote Models
84
+
85
+ Fetching your API by calling "fetch" on your model class:
86
+
87
+ ```ruby
88
+ Task.fetch("https://example.com/tasks")
89
+ ```
90
+
91
+ **Example Response**
92
+ ```javascript
93
+ [{
94
+ "id": 1,
95
+ "name": 'Buy beer',
96
+ "long_name": 'Many, many, many beer!',
97
+ "due_date": "2013-11-03T20:40:00+01:00",
98
+ "updated_at": "2013-11-03T20:20:10+01:00",
99
+ "created_at": "2013-11-03T20:06:01+01:00"
100
+ },{
101
+ "id": 2,
102
+ "name": 'Drink beer',
103
+ "long_name": 'Beer, beer, beer, beer',
104
+ "due_date": "2013-11-03T21:40:00+01:00",
105
+ "updated_at": "2013-11-03T20:20:10+01:00",
106
+ "created_at": "2013-11-03T20266:01+01:00"
107
+ }]
108
+ ```
109
+
110
+ After this call, you will have a bunch of records in your collection.
111
+ If you want to have a direct callback, after the new records have stored, you can call the method with a block:
112
+
113
+ ```ruby
114
+ Task.fetch("https://example.com/tasks") do |tasks|
115
+ tasks.each do |task|
116
+ puts task.name
117
+ end
118
+ end
119
+ ```
120
+
121
+ If you need specific URL parameters, you can add them as the second parameter:
122
+ ```ruby
123
+ Task.fetch("https://example.com/tasks", {api_key: "top_secret!"})
124
+ ```
125
+
126
+ If you want to update an existing record, you can use the instance method fetch.
127
+ ```ruby
128
+ task = Task.first
129
+ task.fetch("https://example.com/tasks")
130
+ ```
131
+
132
+ **Tip:** If you have the lastSyncedAt column in your model, this will automatacally set to the current timestamp!
133
+
134
+
135
+ ### Saving Remote Models
136
+
137
+ If you want to store your local model, you can simply do this with MotionModelResource. You just need to configure an url class method and giving a block for the save method:
138
+
139
+ ```ruby
140
+ task = Task.first
141
+ task.name = "Drinking a lot of soda"
142
+ task.save do |model|
143
+ if model.present?
144
+ puts "task saved!"
145
+ else
146
+ puts "Damn, something went wrong..."
147
+ end
148
+ end
149
+ ```
150
+
151
+ The task object will update, too. As you can see, if the model var is nil, the save process had failed.
152
+ The save method will store the relations too!! It will serialize the whole model and push this to the server. The mapping information comes also from the wrapper method.
data/Rakefile ADDED
@@ -0,0 +1,18 @@
1
+ # -*- coding: utf-8 -*-
2
+ require "bundler/gem_tasks"
3
+ $:.unshift("/Library/RubyMotion/lib")
4
+ require 'motion/project/template/ios'
5
+ require 'bundler'
6
+ Bundler.require
7
+
8
+ $:.unshift(File.expand_path('../lib', __FILE__))
9
+ require 'motion_model_resource'
10
+ require 'bubble-wrap/core'
11
+ require 'bubble-wrap/http'
12
+
13
+ Motion::Project::App.setup do |app|
14
+ # Use `rake config' to see complete project settings.
15
+ app.name = 'MotionModelResource'
16
+ app.delegate_class = 'FakeDelegate'
17
+ app.files = (app.files + Dir.glob('./app/**/*.rb')).uniq
18
+ end
@@ -0,0 +1,2 @@
1
+ class FakeDelegate
2
+ end
@@ -0,0 +1,5 @@
1
+ Motion::Project::App.setup do |app|
2
+ Dir.glob(File.join(File.expand_path('../../motion/**/*.rb', __FILE__))).each do |file|
3
+ app.files.unshift(file)
4
+ end
5
+ end
@@ -0,0 +1,13 @@
1
+ module MotionModelResource
2
+ module DateParser
3
+ def self.parseDate(arg)
4
+ date_formatter = NSDateFormatter.alloc.init
5
+ date_formatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ssZZZZ"
6
+ date = date_formatter.dateFromString arg
7
+
8
+ return nil if date.blank?
9
+
10
+ date.description
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,206 @@
1
+ module MotionModelResource
2
+ class WrapperNotDefinedError < Exception; end
3
+ class URLNotDefinedError < Exception; end
4
+ class ActionNotImplemented < Exception; end
5
+
6
+ module ApiWrapper
7
+ def self.included(base)
8
+ base.extend(PublicClassMethods)
9
+ end
10
+
11
+ module PublicClassMethods
12
+ # Returns the last updated at or nil value of Model
13
+ def lastUpdate
14
+ order(:updated_at).first.try(:updated_at)
15
+ end
16
+
17
+ # Loads the given URL and parse the JSON for new models.
18
+ # If the models are present, the model will update.
19
+ # If block given, the block will called, when the the models are saved. The model/s will be passed as an argument to the block.
20
+ def fetch(site, params = {}, &block)
21
+ raise MotionModelResource::WrapperNotDefinedError.new "Wrapper is not defined!" unless self.respond_to?(:wrapper)
22
+ BW::HTTP.get(site, params) do |response|
23
+ models = []
24
+ if response.ok? && response.body.present?
25
+ json = BW::JSON.parse(response.body.to_str)
26
+ models = updateModels(json)
27
+ end
28
+
29
+ block.call(models) if block.present? && block.respond_to?(:call)
30
+ end
31
+ end
32
+
33
+ # Parses given JSON object and saves the founded models.
34
+ # Returns an array with models, or the founded model
35
+ def updateModels(json)
36
+ if json.is_a?(Array)
37
+ models = []
38
+ for jsonPart in json
39
+ model = buildModel(jsonPart)
40
+ if model.present?
41
+ model.save
42
+ models << model
43
+ end
44
+ end
45
+ return models
46
+ else
47
+ model = buildModel(json)
48
+ if model.present?
49
+ model.save
50
+ return model
51
+ end
52
+ end
53
+ end
54
+
55
+ # Builds a model for given JSON object. Returns a new or presend model.
56
+ def buildModel(json)
57
+ classname = name.downcase
58
+
59
+ model = where("id").eq(json["id"]).first
60
+ if model.present?
61
+ if model.wrap(json)
62
+ model.lastSyncAt = Time.now if model.respond_to?(:lastSyncAt)
63
+ return model
64
+ end
65
+ else
66
+ newModel = self.new
67
+ return newModel if newModel.wrap(json)
68
+ end
69
+
70
+ return nil
71
+ end
72
+ end
73
+
74
+ # Instance methods
75
+
76
+ # Saves the current model. Calls super when block is not given.
77
+ # If block is given, the url method will be needed to call the remote server.
78
+ # The answer of the server will be parsed and stored.
79
+ # If the record is a new one, a POST request will be fired, otherwise a PUT call comes to the server.
80
+ def save(options = {}, &block)
81
+ if block.present?
82
+ raise MotionModelResource::URLNotDefinedError.new "URL is not defined for #{self.class.name}!" unless self.class.respond_to?(:url)
83
+
84
+ action = if new_record?
85
+ "create"
86
+ elsif self.id.present?
87
+ "update"
88
+ else
89
+ raise MotionModelResource::ActionNotImplemented.new "Action ist not implemented for #{self.class.name}!"
90
+ end
91
+
92
+ model = self
93
+
94
+ model.id = nil if model.id.present? && action == "create"
95
+
96
+ hash = buildHashFromModel(self.class.name.downcase, self)
97
+ hash.merge!(options[:params]) if options[:params].present?
98
+
99
+ requestBlock = Proc.new do |response|
100
+ if response.ok? && response.body.present?
101
+ json = BW::JSON.parse(response.body.to_str)
102
+
103
+ model.wrap(json)
104
+ model.lastSyncAt = Time.now if model.respond_to?(:lastSyncAt)
105
+ model.save
106
+ else
107
+ model = nil
108
+ end
109
+
110
+ block.call(model) if block.present? && block.respond_to?(:call)
111
+ end
112
+
113
+ case action
114
+ when "create"
115
+ BW::HTTP.post(self.class.url, {payload: hash}, &requestBlock)
116
+ when "update"
117
+ BW::HTTP.put("#{self.class.url}/#{model.id}", {payload: hash}, &requestBlock)
118
+ end
119
+ else
120
+ super
121
+ end
122
+ end
123
+
124
+ # Returns a hash with given model
125
+ def buildHashFromModel(mainKey, model)
126
+ hash = {
127
+ mainKey => {}
128
+ }
129
+ hash[mainKey] = {}
130
+
131
+ model.attributes.each do |key, attribute|
132
+ if model.class.has_many_columns.keys.include?(key)
133
+ newKey = attribute.first.class.name.pluralize.downcase
134
+ hash[mainKey][newKey] = []
135
+ for a in attribute
136
+ hash[mainKey][newKey].push(buildHashFromModel(newKey, a)[newKey])
137
+ end
138
+ elsif attribute.respond_to?(:attributes)
139
+ newKey = attribute.class.name.downcase
140
+ h = buildHashFromModel(newKey, attribute)
141
+ hash[mainKey][newKey] = h[newKey] if h.has_key?(newKey)
142
+ else
143
+ model.class.wrapper[:fields].each do |wrapperKey, wrapperValue|
144
+ hash[mainKey][wrapperKey] = attribute if wrapperValue == key
145
+ end
146
+ end
147
+ end
148
+
149
+ return hash
150
+ end
151
+
152
+ # Loads the given URL and parse the JSON for a model.
153
+ # If the model is present, the model will updates.
154
+ # If block given, the block will called, when the the model is saved. The model will be passed as an argument to the block.
155
+ def fetch(site, params, &block)
156
+ raise MotionModelResource::WrapperNotDefinedError.new "Wrapper is not defined!" unless self.class.respond_to?(:wrapper)
157
+ model = self
158
+ BW::HTTP.get(site, params) do |response|
159
+ if response.ok? && response.body.present?
160
+ json = BW::JSON.parse(response.body.to_str)
161
+ model.wrap(json)
162
+ model.lastSyncAt = Time.now if model.respond_to?(:lastSyncAt)
163
+
164
+ model.save
165
+ end
166
+
167
+ block.call if block.present? && block.respond_to?(:call)
168
+ end
169
+ end
170
+
171
+ # Wraps the current model with the given JSON.
172
+ # All the fields found in JSON and self.wrapper will be parsed.
173
+ # Returns true, when no error exists
174
+ def wrap(modelJson)
175
+ return unless self.class.respond_to?(:wrapper)
176
+
177
+ self.class.wrapper[:fields].each do |online, local|
178
+ if modelJson.respond_to?("key?") && modelJson.key?("#{online}")
179
+ value = parseValue(local, modelJson[online])
180
+ self.send("#{local}=", value)
181
+ end
182
+ end
183
+
184
+ if self.class.wrapper[:relations].present?
185
+ self.class.wrapper[:relations].each do |relation|
186
+ if modelJson.respond_to?("key?") && modelJson.key?("#{relation}") && modelJson["#{relation}"].present?
187
+ klass = Object.const_get(relation.to_s.singularize.camelize)
188
+ newRelation = klass.updateModels(modelJson["#{relation}"])
189
+ self.send("#{relation}=", newRelation) rescue NoMethodError # not correct implemented in MotionModel
190
+ end
191
+ end
192
+ end
193
+
194
+ true
195
+ end
196
+
197
+ # Parses given value for key in the right format for MotionModel.
198
+ # Currently only Date/Time support needed
199
+ def parseValue(key, value)
200
+ case self.column_type(key.to_sym)
201
+ when :date, :time then MotionModelResource::DateParser.parseDate value
202
+ else value
203
+ end
204
+ end
205
+ end
206
+ end
data/motion/version.rb ADDED
@@ -0,0 +1,3 @@
1
+ module MotionModelResource
2
+ VERSION = "0.1.6"
3
+ end
@@ -0,0 +1,21 @@
1
+ # -*- encoding: utf-8 -*-
2
+ require File.expand_path('../motion/version', __FILE__)
3
+
4
+ Gem::Specification.new do |gem|
5
+ gem.authors = ["Torben Toepper"]
6
+ gem.email = ["lshadyl@googlemail.com"]
7
+ gem.description = "Simple JSON API Wrapper for MotionModel on RubyMotion"
8
+ gem.summary = "Simple JSON API Wrapper for MotionModel on RubyMotion"
9
+ gem.homepage = "https://github.com/torben/motion-resource"
10
+
11
+ gem.files = `git ls-files`.split($\)
12
+ gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
13
+ gem.name = "motion_model_resource"
14
+ gem.require_paths = ["lib"]
15
+ gem.add_dependency 'bubble-wrap', '>= 1.3.0'
16
+ gem.add_dependency 'motion-support', '>=0.1.0'
17
+ gem.add_dependency 'motion_model', '>=0.4.4'
18
+ gem.add_dependency 'webstub', '>=0.3.0'
19
+ gem.version = MotionModelResource::VERSION
20
+ gem.licenses = ["MIT"]
21
+ end
@@ -0,0 +1,186 @@
1
+ class UserWithOutWrapper
2
+ include MotionModel::Model
3
+ include MotionModel::ArrayModelAdapter
4
+ include MotionModelResource::ApiWrapper
5
+ columns name: :string,
6
+ email: :string,
7
+ age: :integer,
8
+ admin: :boolean
9
+ end
10
+
11
+ class User
12
+ include MotionModel::Model
13
+ include MotionModel::ArrayModelAdapter
14
+ include MotionModelResource::ApiWrapper
15
+
16
+ def self.url
17
+ "http://example.com/users"
18
+ end
19
+
20
+ def self.wrapper
21
+ @wrapper ||= {
22
+ fields: {
23
+ id: :id,
24
+ plan_id: :plan_id,
25
+ name: :name,
26
+ email: :email,
27
+ age: :age,
28
+ admin: :admin
29
+ },
30
+ relations: [:tasks, :plan]
31
+ }
32
+ end
33
+
34
+ columns name: :string,
35
+ plan_id: :plan_id,
36
+ email: :string,
37
+ age: :integer,
38
+ admin: :boolean
39
+
40
+ has_many :tasks
41
+ belongs_to :plan
42
+ end
43
+
44
+ class Task
45
+ include MotionModel::Model
46
+ include MotionModel::ArrayModelAdapter
47
+ include MotionModelResource::ApiWrapper
48
+
49
+ def self.url
50
+ "http://example.com/tasks"
51
+ end
52
+
53
+ def self.wrapper
54
+ @wrapper ||= {
55
+ fields: {
56
+ id: :id,
57
+ user_id: :user_id,
58
+ name: :name,
59
+ },
60
+ relations: [:user]
61
+ }
62
+ end
63
+
64
+ columns name: :string
65
+ belongs_to :user
66
+ end
67
+
68
+ class Plan
69
+ include MotionModel::Model
70
+ include MotionModel::ArrayModelAdapter
71
+ include MotionModelResource::ApiWrapper
72
+
73
+ def self.url
74
+ "http://example.com/plans"
75
+ end
76
+
77
+ def self.wrapper
78
+ @wrapper ||= {
79
+ fields: {
80
+ id: :id,
81
+ name: :name,
82
+ },
83
+ relations: [:users]
84
+ }
85
+ end
86
+
87
+ columns name: :string
88
+ has_many :users
89
+ end
90
+
91
+ describe "Fetching a model" do
92
+ extend WebStub::SpecHelpers
93
+
94
+ it "should not wrap a model without wrapper method" do
95
+ lambda{
96
+ UserWithOutWrapper.fetch("http://localhost:3000/users/1")
97
+ }.should.raise(MotionModelResource::WrapperNotDefinedError)
98
+ end
99
+
100
+ it "should create a new model with API call" do
101
+ user_url = "http://localhost:3000/users/1"
102
+ stub_request(:get, user_url).to_return(json: {
103
+ name: "Peter",
104
+ email: "peter@pan.de",
105
+ age: 14,
106
+ admin: false
107
+ })
108
+
109
+ User.fetch(user_url) do |model|
110
+ resume
111
+ end
112
+
113
+ wait_max 1.0 do
114
+ user = User.first
115
+ user.should.not == nil
116
+ User.count.should.equal(1)
117
+ user.name.should.equal("Peter")
118
+ user.email.should.equal("peter@pan.de")
119
+ user.age.should.equal(14)
120
+ user.admin.should.equal(false)
121
+ end
122
+ end
123
+
124
+ it "should create a new model with dependencies" do
125
+ User.delete_all
126
+ Task.delete_all
127
+ Plan.delete_all
128
+
129
+ user_url = "http://localhost:3000/users/10"
130
+ stub_request(:get, user_url).to_return(json: {
131
+ id: 10,
132
+ plan_id: 5,
133
+ name: "Manuel",
134
+ email: "manuel@dudda.de",
135
+ age: 28,
136
+ admin: true,
137
+ tasks: [
138
+ {
139
+ id: 1,
140
+ name: 'Cleaning up the closet',
141
+ user_id: 10
142
+ },
143
+ {
144
+ id: 2,
145
+ name: 'Drinking soda',
146
+ user_id: 10
147
+ }
148
+ ],
149
+ plan: {
150
+ id: 5,
151
+ name: 'Gold'
152
+ }
153
+ })
154
+
155
+ User.fetch(user_url) do |model|
156
+ resume
157
+ end
158
+
159
+ wait_max 1.0 do
160
+ User.count.should.equal(1)
161
+ Plan.count.should.equal(1)
162
+ Task.count.should.equal(2)
163
+
164
+ user = User.find(10)
165
+ user.plan.name.should.equal("Gold")
166
+ user.tasks.first.name.should.equal("Cleaning up the closet")
167
+ user.tasks.last.name.should.equal("Drinking soda")
168
+ end
169
+ end
170
+
171
+ describe '#parseValue' do
172
+ it 'should parse a date in the right format for MotionModel' do
173
+ time_string = "2013-11-03T16:59:35+01:00"
174
+
175
+ MotionModelResource::DateParser.parseDate(time_string).should.equal("2013-11-03 15:59:35 +0000")
176
+ end
177
+
178
+ it 'should return nil, when giving a wrong time' do
179
+ time_string = "2342"
180
+ time_string2 = "2013-21-03T16:59:35+01:00"
181
+
182
+ MotionModelResource::DateParser.parseDate(time_string).should.equal nil
183
+ MotionModelResource::DateParser.parseDate(time_string2).should.equal nil
184
+ end
185
+ end
186
+ end
metadata ADDED
@@ -0,0 +1,125 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: motion_model_resource
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.6
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Torben Toepper
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2013-11-14 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: bubble-wrap
16
+ requirement: !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ! '>='
20
+ - !ruby/object:Gem::Version
21
+ version: 1.3.0
22
+ type: :runtime
23
+ prerelease: false
24
+ version_requirements: !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ! '>='
28
+ - !ruby/object:Gem::Version
29
+ version: 1.3.0
30
+ - !ruby/object:Gem::Dependency
31
+ name: motion-support
32
+ requirement: !ruby/object:Gem::Requirement
33
+ none: false
34
+ requirements:
35
+ - - ! '>='
36
+ - !ruby/object:Gem::Version
37
+ version: 0.1.0
38
+ type: :runtime
39
+ prerelease: false
40
+ version_requirements: !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ! '>='
44
+ - !ruby/object:Gem::Version
45
+ version: 0.1.0
46
+ - !ruby/object:Gem::Dependency
47
+ name: motion_model
48
+ requirement: !ruby/object:Gem::Requirement
49
+ none: false
50
+ requirements:
51
+ - - ! '>='
52
+ - !ruby/object:Gem::Version
53
+ version: 0.4.4
54
+ type: :runtime
55
+ prerelease: false
56
+ version_requirements: !ruby/object:Gem::Requirement
57
+ none: false
58
+ requirements:
59
+ - - ! '>='
60
+ - !ruby/object:Gem::Version
61
+ version: 0.4.4
62
+ - !ruby/object:Gem::Dependency
63
+ name: webstub
64
+ requirement: !ruby/object:Gem::Requirement
65
+ none: false
66
+ requirements:
67
+ - - ! '>='
68
+ - !ruby/object:Gem::Version
69
+ version: 0.3.0
70
+ type: :runtime
71
+ prerelease: false
72
+ version_requirements: !ruby/object:Gem::Requirement
73
+ none: false
74
+ requirements:
75
+ - - ! '>='
76
+ - !ruby/object:Gem::Version
77
+ version: 0.3.0
78
+ description: Simple JSON API Wrapper for MotionModel on RubyMotion
79
+ email:
80
+ - lshadyl@googlemail.com
81
+ executables: []
82
+ extensions: []
83
+ extra_rdoc_files: []
84
+ files:
85
+ - .gitignore
86
+ - CHANGELOG
87
+ - Gemfile
88
+ - Gemfile.lock
89
+ - LICENSE
90
+ - README.md
91
+ - Rakefile
92
+ - app/app_delegate.rb
93
+ - lib/motion_model_resource.rb
94
+ - motion/resource/data_parser.rb
95
+ - motion/resource/wrapper.rb
96
+ - motion/version.rb
97
+ - motion_model_resource.gemspec
98
+ - spec/wrapper_spec.rb
99
+ homepage: https://github.com/torben/motion-resource
100
+ licenses:
101
+ - MIT
102
+ post_install_message:
103
+ rdoc_options: []
104
+ require_paths:
105
+ - lib
106
+ required_ruby_version: !ruby/object:Gem::Requirement
107
+ none: false
108
+ requirements:
109
+ - - ! '>='
110
+ - !ruby/object:Gem::Version
111
+ version: '0'
112
+ required_rubygems_version: !ruby/object:Gem::Requirement
113
+ none: false
114
+ requirements:
115
+ - - ! '>='
116
+ - !ruby/object:Gem::Version
117
+ version: '0'
118
+ requirements: []
119
+ rubyforge_project:
120
+ rubygems_version: 1.8.24
121
+ signing_key:
122
+ specification_version: 3
123
+ summary: Simple JSON API Wrapper for MotionModel on RubyMotion
124
+ test_files:
125
+ - spec/wrapper_spec.rb