motion-resource 0.0.2 → 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/.gitignore CHANGED
@@ -7,3 +7,4 @@ resources/*.storyboardc
7
7
  .bundle
8
8
  Gemfile.lock
9
9
  pkg/*
10
+ .dat*
data/README.md CHANGED
@@ -12,22 +12,22 @@ Add MotionResource to your Gemfile, like this:
12
12
 
13
13
  Consider this example for a fictional blog API.
14
14
 
15
- class User < RemoteModule::RemoteModel
15
+ class User < MotionResource::Base
16
16
  attr_accessor :id
17
17
 
18
18
  has_many :posts
19
19
 
20
- collection_url "users"
21
- member_url "users/:id"
20
+ self.collection_url = "users"
21
+ self.member_url = "users/:id"
22
22
  end
23
23
 
24
- class Post < RemoteModule::RemoteModel
24
+ class Post < MotionResource::Base
25
25
  attr_accessor :id, :user_id, :title, :text
26
26
 
27
27
  belongs_to :user
28
28
 
29
- collection_url "users/:user_id/posts"
30
- member_url "users/:user_id/posts/:id"
29
+ self.collection_url = "users/:user_id/posts"
30
+ self.member_url = "users/:user_id/posts/:id"
31
31
  end
32
32
 
33
33
  Now, we can access a user's posts like that:
data/Rakefile CHANGED
@@ -5,10 +5,10 @@ require "bundler/gem_tasks"
5
5
  Bundler.setup
6
6
  Bundler.require
7
7
 
8
- $:.unshift("./lib/")
9
- require './lib/motion-resource'
8
+ require 'motion-resource'
10
9
 
11
10
  Motion::Project::App.setup do |app|
12
11
  # Use `rake config' to see complete project settings.
13
12
  app.name = 'MotionResource'
14
- end
13
+ app.detect_dependencies = false
14
+ end
@@ -1,10 +1,11 @@
1
1
  # -*- coding: utf-8 -*-
2
2
  $:.unshift("/Library/RubyMotion/lib")
3
3
  require 'motion/project'
4
- require 'motion-support'
5
- require 'motion-resource'
4
+
5
+ require '../../lib/motion-resource'
6
6
 
7
7
  Motion::Project::App.setup do |app|
8
8
  # Use `rake config' to see complete project settings.
9
9
  app.name = 'Colr'
10
+ app.detect_dependencies = false
10
11
  end
@@ -1,6 +1,7 @@
1
1
  module MotionResource
2
2
  class Base
3
- class_inheritable_array :attributes
3
+ class_attribute :attributes
4
+ self.attributes = []
4
5
 
5
6
  class << self
6
7
  def attribute(*fields)
@@ -1,6 +1,6 @@
1
1
  module MotionResource
2
2
  class Base
3
- class_inheritable_accessor :logger
3
+ class_attribute :logger
4
4
  self.logger = MotionSupport::NullLogger.new
5
5
  end
6
6
  end
@@ -7,7 +7,7 @@ module MotionResource
7
7
  self.class.send(method, *args, &block)
8
8
  end
9
9
  end
10
-
10
+
11
11
  class << self
12
12
  def get(url, params = {}, &block)
13
13
  http_call(:get, url, params, &block)
@@ -25,6 +25,10 @@ module MotionResource
25
25
  http_call(:delete, url, params, &block)
26
26
  end
27
27
 
28
+ def on_auth_failure(&block)
29
+ @on_auth_failure = block
30
+ end
31
+
28
32
  private
29
33
  def complete_url(fragment)
30
34
  if fragment[0..3] == "http"
@@ -34,20 +38,21 @@ module MotionResource
34
38
  end
35
39
 
36
40
  def http_call(method, url, call_options = {}, &block)
37
- options = call_options
41
+ url = complete_url(url)
42
+
43
+ options = call_options
38
44
  options.merge!(MotionResource::Base.default_url_options || {})
39
- url += self.extension
40
45
  if query = options.delete(:query)
41
- if url.index("?").nil?
42
- url += "?"
43
- end
44
- url += query.map{|k,v| "#{k}=#{v}"}.join('&')
46
+ url.build_query_string!(query)
45
47
  end
46
48
  if self.default_url_options
47
49
  options.merge!(self.default_url_options)
48
50
  end
49
- logger.log "#{method.upcase} #{complete_url(url)}"
50
- BubbleWrap::HTTP.send(method, complete_url(url), options) do |response|
51
+ logger.log "#{method.upcase} #{url}"
52
+
53
+ url.insert_extension!(self.extension)
54
+
55
+ BubbleWrap::HTTP.send(method, url, options) do |response|
51
56
  if response.ok?
52
57
  body = response.body.to_str.strip rescue nil
53
58
  logger.log "response: #{body}"
@@ -56,6 +61,8 @@ module MotionResource
56
61
  else
57
62
  block.call response, BubbleWrap::JSON.parse(body)
58
63
  end
64
+ elsif response.status_code.to_s =~ /401/ && @on_auth_failure
65
+ @on_auth_failure.call
59
66
  else
60
67
  block.call response, nil
61
68
  end
@@ -4,7 +4,7 @@ class String
4
4
  def fill_url_params(params = {}, delegate = nil)
5
5
  params ||= {}
6
6
  split = self.split '/'
7
- split.collect { |path|
7
+ url = split.collect { |path|
8
8
  ret = path
9
9
  if path[0] == ':'
10
10
  path_sym = path[1..-1].to_sym
@@ -14,10 +14,33 @@ class String
14
14
  curr = delegate.send(path_sym)
15
15
  end
16
16
 
17
- ret = (curr || params[path_sym] || path).to_s
17
+ ret = (curr || params.delete(path_sym) || path).to_s
18
18
  end
19
19
 
20
20
  ret
21
21
  }.join '/'
22
+ url.build_query_string! params
23
+ end
24
+
25
+ def build_query_string!(params = {})
26
+ return self if params.keys.empty?
27
+ # fake a url so we avoid regex nastiness with URL's
28
+ url = NSURL.URLWithString("http://blah.com/#{self}")
29
+ # build our query string (needs encoding support!)
30
+ query_string = params.map{|k,v| "#{k}=#{v}"}.join('&')
31
+ if url.query.nil? || url.query.empty?
32
+ # strip the beginning / and add the query
33
+ self.replace "#{url.path[1..-1]}?#{query_string}"
34
+ else
35
+ self.replace "#{url.path[1..-1]}?#{url.query}&#{query_string}"
36
+ end
37
+ end
38
+
39
+ def insert_extension!(extension)
40
+ return self if extension.blank?
41
+
42
+ url = NSURL.URLWithString(self)
43
+ extension = extension.gsub(".", "")
44
+ self.replace url.URLByAppendingPathExtension(extension).absoluteString
22
45
  end
23
46
  end
@@ -1,8 +1,8 @@
1
1
  module MotionResource
2
2
  class Base
3
- class_inheritable_accessor :collection_url, :member_url
4
- class_inheritable_accessor :root_url, :default_url_options
5
- class_inheritable_accessor :extension
3
+ class_attribute :collection_url, :member_url
4
+ class_attribute :root_url, :default_url_options
5
+ class_attribute :extension
6
6
  self.extension = '.json'
7
7
 
8
8
  class << self
@@ -1,3 +1,3 @@
1
1
  module MotionResource
2
- VERSION = "0.0.2"
2
+ VERSION = "0.1.0"
3
3
  end
@@ -1,5 +1,4 @@
1
- require "motion-resource/version"
1
+ require 'motion-support'
2
2
  require 'bubble-wrap'
3
- Dir.glob(File.join(File.dirname(__FILE__), 'motion-resource/*.rb')).each do |file|
4
- BW.require file
5
- end
3
+
4
+ Motion::Require.all(Dir.glob(File.expand_path('../motion-resource/**/*.rb', __FILE__)))
@@ -15,6 +15,6 @@ Gem::Specification.new do |s|
15
15
  s.require_paths = ["lib"]
16
16
 
17
17
  s.add_dependency 'bubble-wrap'
18
- s.add_dependency 'motion-support'
18
+ s.add_dependency 'motion-support', ">= 0.2.0"
19
19
  s.add_development_dependency 'rake'
20
20
  end
@@ -1,6 +1,6 @@
1
1
  describe "requests" do
2
2
  extend WebStub::SpecHelpers
3
-
3
+
4
4
  it "should define GET method on instance and class" do
5
5
  Comment.new.should.respond_to :get
6
6
  Comment.should.respond_to :get
@@ -20,100 +20,113 @@ describe "requests" do
20
20
  Comment.new.should.respond_to :delete
21
21
  Comment.should.respond_to :delete
22
22
  end
23
-
23
+
24
24
  it "should add query string" do
25
25
  stub_request(:get, "http://example.com/comments/10.json?foo=bar").to_return(json: { id: 10 })
26
26
  Comment.new.get("comments/10", :query => { :foo => 'bar' }) do |response, json|
27
27
  @result = json
28
28
  resume
29
29
  end
30
-
30
+
31
31
  wait_max 1.0 do
32
32
  @result.should.not.be.nil
33
33
  end
34
34
  end
35
-
35
+
36
36
  it "should parse JSON in response" do
37
37
  stub_request(:get, "http://example.com/comments/10.json").to_return(json: { id: 10, foo: 'bar' })
38
38
  Comment.new.get("comments/10") do |response, json|
39
39
  @result = json
40
40
  resume
41
41
  end
42
-
42
+
43
43
  wait_max 1.0 do
44
44
  @result.should == { "id" => 10, "foo" => "bar" }
45
45
  end
46
46
  end
47
-
47
+
48
48
  it "should yield empty hash if response is blank" do
49
49
  stub_request(:get, "http://example.com/comments/10.json").to_return(body: "")
50
50
  Comment.new.get("comments/10") do |response, json|
51
51
  @result = json
52
52
  resume
53
53
  end
54
-
54
+
55
55
  wait_max 1.0 do
56
56
  @result.should == {}
57
57
  end
58
58
  end
59
-
59
+
60
60
  it "should yield nil if response is not ok" do
61
61
  stub_request(:get, "http://example.com/comments/10.json").to_return(status_code: 404)
62
62
  Comment.new.get("comments/10") do |response, json|
63
63
  @result = json
64
64
  resume
65
65
  end
66
-
66
+
67
67
  wait_max 1.0 do
68
68
  @result.should.be.nil
69
69
  end
70
70
  end
71
-
71
+
72
72
  it "should get attributes" do
73
73
  stub_request(:get, "http://example.com/comments/10.json").to_return(json: { id: 10, text: "Hello" })
74
74
  Comment.new.get("comments/10") do |response, json|
75
75
  @result = json
76
76
  resume
77
77
  end
78
-
78
+
79
79
  wait_max 1.0 do
80
80
  @result["text"].should == "Hello"
81
81
  end
82
82
  end
83
-
83
+
84
84
  it "should post" do
85
85
  stub_request(:post, "http://example.com/comments.json").to_return(json: { id: 10 })
86
86
  Comment.post("comments") do |response, json|
87
87
  @result = json
88
88
  resume
89
89
  end
90
-
90
+
91
91
  wait_max 1.0 do
92
92
  @result.should.not.be.nil
93
93
  end
94
94
  end
95
-
95
+
96
96
  it "should put" do
97
97
  stub_request(:put, "http://example.com/comments/10.json").to_return(json: { id: 10 })
98
98
  Comment.new.put("comments/10") do |response, json|
99
99
  @result = json
100
100
  resume
101
101
  end
102
-
102
+
103
103
  wait_max 1.0 do
104
104
  @result.should.not.be.nil
105
105
  end
106
106
  end
107
-
107
+
108
108
  it "should delete" do
109
109
  stub_request(:delete, "http://example.com/comments/10.json").to_return(json: { id: 10 })
110
110
  Comment.new.delete("comments/10") do |response, json|
111
111
  @result = json
112
112
  resume
113
113
  end
114
-
114
+
115
115
  wait_max 1.0 do
116
116
  @result.should.not.be.nil
117
117
  end
118
118
  end
119
+
120
+ it "should call a block given to on_auth_failure on 401" do
121
+ stub_request(:get, "http://example.com/comments/10.json").to_return(status_code: 401)
122
+ @fail = false
123
+ Comment.on_auth_failure { @fail = true; resume }
124
+ Comment.new.get("comments/10") do |response, json|
125
+ resume
126
+ end
127
+
128
+ wait_max 1.0 do
129
+ @fail.should == true
130
+ end
131
+ end
119
132
  end
@@ -7,7 +7,32 @@ describe "String" do
7
7
  string = "accounts/:id/users/:name".fill_url_params(id: 10, name: 'john')
8
8
  string.should == "accounts/10/users/john"
9
9
  end
10
-
10
+
11
+ it "should insert an extension if missing" do
12
+ string = "accounts/fabulous".insert_extension!(".json")
13
+ string.should == "accounts/fabulous.json"
14
+ end
15
+
16
+ it "should not insert extension if it is blank" do
17
+ string = "accounts/fabulous".insert_extension!("")
18
+ string.should == "accounts/fabulous"
19
+ end
20
+
21
+ it "should add a query string for non-url params" do
22
+ string = "accounts/fabulous".build_query_string!(foo: 10, moo: "rar")
23
+ string.should == "accounts/fabulous?foo=10&moo=rar"
24
+ end
25
+
26
+ it "should not add a ? when building a query string if it exists" do
27
+ string = "accounts/fabulous?".build_query_string!(foo: 10, moo: "rar")
28
+ string.should == "accounts/fabulous?foo=10&moo=rar"
29
+ end
30
+
31
+ it "should tag new query params onto existing ones" do
32
+ string = "accounts/fabulous?moo=rar".build_query_string!(foo: 10)
33
+ string.should == "accounts/fabulous?moo=rar&foo=10"
34
+ end
35
+
11
36
  it "should fill url params from delegate object" do
12
37
  obj = DelegateObject.new
13
38
  obj.id = 10
@@ -15,11 +40,11 @@ describe "String" do
15
40
  string = "accounts/:id/users/:name".fill_url_params({}, obj)
16
41
  string.should == "accounts/10/users/john"
17
42
  end
18
-
43
+
19
44
  it "should not crash when a param is unknown" do
20
45
  lambda { "accounts/:id".fill_url_params({}) }.should.not.raise
21
46
  end
22
-
47
+
23
48
  it "should not crash when params hash contains an unused value" do
24
49
  lambda { "accounts".fill_url_params(foo: 'bar') }.should.not.raise
25
50
  end
metadata CHANGED
@@ -2,7 +2,7 @@
2
2
  name: motion-resource
3
3
  version: !ruby/object:Gem::Version
4
4
  prerelease:
5
- version: 0.0.2
5
+ version: 0.1.0
6
6
  platform: ruby
7
7
  authors:
8
8
  - Thomas Kadauke
@@ -10,7 +10,7 @@ autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
12
 
13
- date: 2012-12-31 00:00:00 Z
13
+ date: 2013-04-29 00:00:00 Z
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
16
  name: bubble-wrap
@@ -30,7 +30,7 @@ dependencies:
30
30
  requirements:
31
31
  - - ">="
32
32
  - !ruby/object:Gem::Version
33
- version: "0"
33
+ version: 0.2.0
34
34
  type: :runtime
35
35
  prerelease: false
36
36
  version_requirements: *id002
@@ -107,7 +107,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
107
107
  requirements:
108
108
  - - ">="
109
109
  - !ruby/object:Gem::Version
110
- hash: -3639208948173529629
110
+ hash: 1896856864951168664
111
111
  segments:
112
112
  - 0
113
113
  version: "0"
@@ -116,7 +116,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
116
116
  requirements:
117
117
  - - ">="
118
118
  - !ruby/object:Gem::Version
119
- hash: -3639208948173529629
119
+ hash: 1896856864951168664
120
120
  segments:
121
121
  - 0
122
122
  version: "0"