motion-resource 0.1.3 → 0.1.4
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/README.md +35 -0
- data/Rakefile +1 -1
- data/lib/motion-resource/associations.rb +11 -6
- data/lib/motion-resource/base.rb +10 -1
- data/lib/motion-resource/crud.rb +27 -8
- data/lib/motion-resource/find.rb +11 -9
- data/lib/motion-resource/requests.rb +25 -16
- data/lib/motion-resource/url_encoder.rb +45 -0
- data/lib/motion-resource/urls.rb +9 -5
- data/lib/motion-resource/version.rb +1 -1
- data/spec/env.rb +8 -3
- data/spec/motion-resource/associations/belongs_to_spec.rb +34 -0
- data/spec/motion-resource/base_spec.rb +10 -0
- data/spec/motion-resource/crud_spec.rb +42 -0
- data/spec/motion-resource/find_spec.rb +14 -0
- data/spec/motion-resource/requests_spec.rb +2 -1
- data/spec/motion-resource/{string_spec.rb → url_encoder_spec.rb} +14 -10
- metadata +7 -7
- data/lib/motion-resource/string.rb +0 -46
data/README.md
CHANGED
@@ -2,6 +2,8 @@
|
|
2
2
|
|
3
3
|
This is a library for using JSON APIs in RubyMotion apps. It is based on [RemoteModel](https://github.com/clayallsopp/remote_model), however it is an almost complete rewrite. Also, it is inspired by ActiveResource.
|
4
4
|
|
5
|
+
This gem needs RubyMotion version 2.3 or higher.
|
6
|
+
|
5
7
|
## Installation
|
6
8
|
|
7
9
|
Add MotionResource to your Gemfile, like this:
|
@@ -43,6 +45,38 @@ Now, we can access a user's posts like that:
|
|
43
45
|
|
44
46
|
Note that the blocks are called asynchronously.
|
45
47
|
|
48
|
+
## URL encoding
|
49
|
+
|
50
|
+
A different url encoding implementation can be substituted by setting MotionResource::Base.url_encoder.
|
51
|
+
For instance to include the fixed parameter 'foo' on every request:
|
52
|
+
|
53
|
+
class CustomEncoder < MotionResource::UrlEncoder
|
54
|
+
def build_query_string(url, params = {})
|
55
|
+
params[:foo] => 42
|
56
|
+
super(url,params)
|
57
|
+
end
|
58
|
+
end
|
59
|
+
MotionResource::Base.url_encoder = CustomEncoder.new
|
60
|
+
|
61
|
+
## Error Handling
|
62
|
+
|
63
|
+
Pass a second block parameter to capture error information:
|
64
|
+
|
65
|
+
User.find_all do |users, response|
|
66
|
+
if response.ok?
|
67
|
+
puts users.inspect
|
68
|
+
else
|
69
|
+
App.alert response.error_message
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
`response` will be an instance of [BubbleWrap::HTTP::Response](http://rdoc.info/github/rubymotion/BubbleWrap/master/file/README.md#HTTP)
|
74
|
+
|
75
|
+
## Reachability
|
76
|
+
|
77
|
+
It's important to check the reachability status of a host before making a request, or you may get intermitent connectivity errors.
|
78
|
+
For an example of how to do so, see `when_reachable` in [TinyMon](https://github.com/tkadauke/TinyMon).
|
79
|
+
|
46
80
|
## Setup
|
47
81
|
|
48
82
|
You can configure every model separately; however you will most likely want to configure things like the root_url the same for every model:
|
@@ -54,3 +88,4 @@ Don't forget the trailing '/' here!
|
|
54
88
|
# Forking
|
55
89
|
|
56
90
|
Feel free to fork and submit pull requests!
|
91
|
+
|
data/Rakefile
CHANGED
@@ -28,7 +28,7 @@ module MotionResource
|
|
28
28
|
|
29
29
|
define_method name do |&block|
|
30
30
|
if block.nil?
|
31
|
-
instance_variable_get("@#{name}") || []
|
31
|
+
instance_variable_get("@#{name}") || instance_variable_set("@#{name}", [])
|
32
32
|
else
|
33
33
|
if cached = instance_variable_get("@#{name}")
|
34
34
|
cached_response = instance_variable_get("@#{name}_response")
|
@@ -67,7 +67,12 @@ module MotionResource
|
|
67
67
|
end
|
68
68
|
end
|
69
69
|
|
70
|
-
def belongs_to(name,
|
70
|
+
def belongs_to(name, options = {})
|
71
|
+
default_options = {
|
72
|
+
:params => lambda { |o| Hash.new },
|
73
|
+
:class_name => name.to_s.classify
|
74
|
+
}
|
75
|
+
options = default_options.merge(options)
|
71
76
|
define_method name do |&block|
|
72
77
|
if block.nil?
|
73
78
|
instance_variable_get("@#{name}")
|
@@ -77,8 +82,8 @@ module MotionResource
|
|
77
82
|
MotionResource::Base.request_block_call(block, cached, cached_response)
|
78
83
|
return
|
79
84
|
end
|
80
|
-
|
81
|
-
|
85
|
+
klass = Object.const_get(options[:class_name])
|
86
|
+
klass.find(self.send("#{name}_id"), options[:params].call(self)) do |result, response|
|
82
87
|
instance_variable_set("@#{name}", result)
|
83
88
|
instance_variable_set("@#{name}_response", response)
|
84
89
|
MotionResource::Base.request_block_call(block, result, response)
|
@@ -87,8 +92,8 @@ module MotionResource
|
|
87
92
|
end
|
88
93
|
|
89
94
|
define_method "#{name}=" do |value|
|
90
|
-
|
91
|
-
value
|
95
|
+
value = Object.const_get(options[:class_name]).instantiate(value) if value.is_a?(Hash)
|
96
|
+
instance_variable_set("@#{name}_id", value.id) if value.respond_to?(:id)
|
92
97
|
instance_variable_set("@#{name}", value)
|
93
98
|
end
|
94
99
|
|
data/lib/motion-resource/base.rb
CHANGED
@@ -18,7 +18,12 @@ module MotionResource
|
|
18
18
|
|
19
19
|
class << self
|
20
20
|
def instantiate(json)
|
21
|
-
|
21
|
+
if json.is_a?(Hash)
|
22
|
+
json = json.symbolize_keys
|
23
|
+
else
|
24
|
+
json = { primary_key => json.to_i }
|
25
|
+
end
|
26
|
+
|
22
27
|
raise ArgumentError, "No :#{primary_key} parameter given for #{self.name}.instantiate" unless json[primary_key]
|
23
28
|
|
24
29
|
klass = if json[:type]
|
@@ -41,6 +46,10 @@ module MotionResource
|
|
41
46
|
result
|
42
47
|
end
|
43
48
|
|
49
|
+
def json_root
|
50
|
+
self.name.underscore.pluralize
|
51
|
+
end
|
52
|
+
|
44
53
|
def identity_map
|
45
54
|
@identity_map ||= {}
|
46
55
|
end
|
data/lib/motion-resource/crud.rb
CHANGED
@@ -1,24 +1,22 @@
|
|
1
1
|
module MotionResource
|
2
2
|
class Base
|
3
|
-
def save(&block)
|
3
|
+
def save(options = {}, &block)
|
4
4
|
run_callbacks :save do
|
5
|
-
@new_record ? create(&block) : update(&block)
|
5
|
+
@new_record ? create(options, &block) : update(options, &block)
|
6
6
|
end
|
7
7
|
end
|
8
8
|
|
9
|
-
def update(&block)
|
9
|
+
def update(options = {}, &block)
|
10
10
|
run_callbacks :update do
|
11
|
-
self.class.put(member_url, :payload =>
|
11
|
+
self.class.put(member_url, :payload => build_payload(options)) do |response, json|
|
12
12
|
self.class.request_block_call(block, json.blank? ? self : self.class.instantiate(json), response) if block
|
13
13
|
end
|
14
14
|
end
|
15
15
|
end
|
16
16
|
|
17
|
-
def create(&block)
|
18
|
-
# weird heisenbug: Specs crash without that line :(
|
19
|
-
dummy = self
|
17
|
+
def create(options = {}, &block)
|
20
18
|
run_callbacks :create do
|
21
|
-
self.class.post(collection_url, :payload =>
|
19
|
+
self.class.post(collection_url, :payload => build_payload(options)) do |response, json|
|
22
20
|
self.class.request_block_call(block, json.blank? ? self : self.class.instantiate(json), response) if block
|
23
21
|
end
|
24
22
|
end
|
@@ -43,5 +41,26 @@ module MotionResource
|
|
43
41
|
self.class.request_block_call(block, json.blank? ? nil : self.class.instantiate(json), response) if block
|
44
42
|
end
|
45
43
|
end
|
44
|
+
|
45
|
+
protected
|
46
|
+
def build_payload(options)
|
47
|
+
includes = Array(options[:include]).inject({}) do |hash, var|
|
48
|
+
if var.to_s =~ /^(.*?)_attributes$/
|
49
|
+
association_name = $1
|
50
|
+
else
|
51
|
+
association_name = var.to_s
|
52
|
+
end
|
53
|
+
|
54
|
+
if respond_to?(association_name)
|
55
|
+
hash[var.to_s] = send(association_name).map(&:attributes)
|
56
|
+
else
|
57
|
+
raise ArgumentError, "No association #{var} found"
|
58
|
+
end
|
59
|
+
|
60
|
+
hash
|
61
|
+
end
|
62
|
+
|
63
|
+
{ self.class.name.underscore => attributes.merge(includes) }
|
64
|
+
end
|
46
65
|
end
|
47
66
|
end
|
data/lib/motion-resource/find.rb
CHANGED
@@ -2,11 +2,11 @@ module MotionResource
|
|
2
2
|
class Base
|
3
3
|
class << self
|
4
4
|
def find(id, params = {}, &block)
|
5
|
-
fetch_member(
|
5
|
+
fetch_member(self.url_encoder.fill_url_params(member_url_or_default, params.merge(id: id)), &block)
|
6
6
|
end
|
7
7
|
|
8
8
|
def find_all(params = {}, &block)
|
9
|
-
fetch_collection(
|
9
|
+
fetch_collection(self.url_encoder.fill_url_params(collection_url_or_default, params), &block)
|
10
10
|
end
|
11
11
|
|
12
12
|
def fetch_member(url, &block)
|
@@ -28,9 +28,9 @@ module MotionResource
|
|
28
28
|
if json.class == Array
|
29
29
|
arr_rep = json
|
30
30
|
elsif json.class == Hash
|
31
|
-
|
32
|
-
if json.has_key?(
|
33
|
-
arr_rep = json[
|
31
|
+
root = self.json_root
|
32
|
+
if json.has_key?(root) || json.has_key?(root.to_sym)
|
33
|
+
arr_rep = json[root] || json[root.to_sym]
|
34
34
|
end
|
35
35
|
else
|
36
36
|
# the returned data was something else
|
@@ -38,9 +38,11 @@ module MotionResource
|
|
38
38
|
request_block_call(block, nil, response)
|
39
39
|
return
|
40
40
|
end
|
41
|
-
arr_rep
|
42
|
-
|
43
|
-
|
41
|
+
if arr_rep
|
42
|
+
arr_rep.each { |one_obj_hash|
|
43
|
+
objs << instantiate(one_obj_hash)
|
44
|
+
}
|
45
|
+
end
|
44
46
|
request_block_call(block, objs, response)
|
45
47
|
else
|
46
48
|
request_block_call(block, nil, response)
|
@@ -63,4 +65,4 @@ module MotionResource
|
|
63
65
|
end
|
64
66
|
end
|
65
67
|
end
|
66
|
-
end
|
68
|
+
end
|
@@ -29,7 +29,27 @@ module MotionResource
|
|
29
29
|
@on_auth_failure = block
|
30
30
|
end
|
31
31
|
|
32
|
-
|
32
|
+
protected
|
33
|
+
|
34
|
+
def decode_response(response, url, options)
|
35
|
+
if response.ok?
|
36
|
+
body = response.body.to_str.strip rescue nil
|
37
|
+
logger.log "response: #{body}"
|
38
|
+
if body.blank?
|
39
|
+
return {}
|
40
|
+
else
|
41
|
+
return BubbleWrap::JSON.parse(body)
|
42
|
+
end
|
43
|
+
else
|
44
|
+
if response.status_code.to_s =~ /401/ && @on_auth_failure
|
45
|
+
@on_auth_failure.call
|
46
|
+
end
|
47
|
+
return nil
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
private
|
52
|
+
|
33
53
|
def complete_url(fragment)
|
34
54
|
if fragment[0..3] == "http"
|
35
55
|
return fragment
|
@@ -43,30 +63,19 @@ module MotionResource
|
|
43
63
|
options = call_options
|
44
64
|
options.merge!(MotionResource::Base.default_url_options || {})
|
45
65
|
if query = options.delete(:query)
|
46
|
-
url.build_query_string
|
66
|
+
url = self.url_encoder.build_query_string(url, query)
|
47
67
|
end
|
48
68
|
if self.default_url_options
|
49
69
|
options.merge!(self.default_url_options)
|
50
70
|
end
|
51
71
|
|
52
|
-
url.insert_extension
|
72
|
+
url = self.url_encoder.insert_extension(url, self.extension)
|
53
73
|
|
54
74
|
logger.log "#{method.upcase} #{url}"
|
75
|
+
logger.log "payload: #{options[:payload]}" if options[:payload]
|
55
76
|
|
56
77
|
BubbleWrap::HTTP.send(method, url, options) do |response|
|
57
|
-
|
58
|
-
body = response.body.to_str.strip rescue nil
|
59
|
-
logger.log "response: #{body}"
|
60
|
-
if body.blank?
|
61
|
-
block.call(response, {})
|
62
|
-
else
|
63
|
-
block.call response, BubbleWrap::JSON.parse(body)
|
64
|
-
end
|
65
|
-
elsif response.status_code.to_s =~ /401/ && @on_auth_failure
|
66
|
-
@on_auth_failure.call
|
67
|
-
else
|
68
|
-
block.call response, nil
|
69
|
-
end
|
78
|
+
block.call response, decode_response(response, url, options)
|
70
79
|
end
|
71
80
|
end
|
72
81
|
end
|
@@ -0,0 +1,45 @@
|
|
1
|
+
module MotionResource
|
2
|
+
class UrlEncoder
|
3
|
+
def fill_url_params(url, params = {}, delegate = nil)
|
4
|
+
params ||= {}
|
5
|
+
url = url.split('/').collect { |path|
|
6
|
+
ret = path
|
7
|
+
if path[0] == ':'
|
8
|
+
path_sym = path[1..-1].to_sym
|
9
|
+
|
10
|
+
curr = nil
|
11
|
+
if delegate && delegate.respond_to?(path_sym)
|
12
|
+
curr = delegate.send(path_sym)
|
13
|
+
end
|
14
|
+
|
15
|
+
ret = (curr || params.delete(path_sym) || path).to_s
|
16
|
+
end
|
17
|
+
|
18
|
+
ret
|
19
|
+
}.join '/'
|
20
|
+
self.build_query_string(url, params)
|
21
|
+
end
|
22
|
+
|
23
|
+
def build_query_string(url, params = {})
|
24
|
+
return url if params.keys.empty?
|
25
|
+
# fake a url so we avoid regex nastiness with URL's
|
26
|
+
url = NSURL.URLWithString("http://blah.com/#{url}")
|
27
|
+
# build our query string (needs encoding support!)
|
28
|
+
query_string = params.to_query
|
29
|
+
if url.query.nil? || url.query.empty?
|
30
|
+
# strip the beginning / and add the query
|
31
|
+
"#{url.path[1..-1]}?#{query_string}"
|
32
|
+
else
|
33
|
+
"#{url.path[1..-1]}?#{url.query}&#{query_string}"
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
def insert_extension(url,extension)
|
38
|
+
return url if extension.blank?
|
39
|
+
|
40
|
+
url = NSURL.URLWithString(url)
|
41
|
+
extension = extension.gsub(".", "")
|
42
|
+
url.URLByAppendingPathExtension(extension).absoluteString
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
data/lib/motion-resource/urls.rb
CHANGED
@@ -3,13 +3,16 @@ module MotionResource
|
|
3
3
|
class_attribute :collection_url, :member_url
|
4
4
|
class_attribute :root_url, :default_url_options
|
5
5
|
class_attribute :extension
|
6
|
+
class_attribute :url_encoder
|
7
|
+
|
6
8
|
self.extension = '.json'
|
7
|
-
|
9
|
+
self.url_encoder = UrlEncoder.new
|
10
|
+
|
8
11
|
class << self
|
9
12
|
def custom_urls(params = {})
|
10
13
|
params.each do |name, url_format|
|
11
|
-
define_method name do |
|
12
|
-
|
14
|
+
define_method name do |method_params = {}|
|
15
|
+
self.url_encoder.fill_url_params(url_format, method_params, self)
|
13
16
|
end
|
14
17
|
define_singleton_method name do
|
15
18
|
url_format
|
@@ -24,14 +27,15 @@ module MotionResource
|
|
24
27
|
def member_url_or_default
|
25
28
|
member_url || "#{name.underscore.pluralize}/:#{primary_key}"
|
26
29
|
end
|
30
|
+
|
27
31
|
end
|
28
32
|
|
29
33
|
def collection_url(params = {})
|
30
|
-
self.class.
|
34
|
+
self.class.url_encoder.fill_url_params(self.class.collection_url_or_default, params, self)
|
31
35
|
end
|
32
36
|
|
33
37
|
def member_url(params = {})
|
34
|
-
self.class.
|
38
|
+
self.class.url_encoder.fill_url_params(self.class.member_url_or_default, params, self)
|
35
39
|
end
|
36
40
|
end
|
37
41
|
end
|
data/spec/env.rb
CHANGED
@@ -10,18 +10,23 @@ class Post < MotionResource::Base
|
|
10
10
|
end
|
11
11
|
|
12
12
|
class Comment < MotionResource::Base
|
13
|
-
attr_accessor :post_id, :text
|
13
|
+
attr_accessor :post_id, :account_id, :text
|
14
14
|
|
15
15
|
self.member_url = 'comments/:id'
|
16
16
|
self.collection_url = 'comments'
|
17
17
|
|
18
18
|
belongs_to :post
|
19
|
-
|
19
|
+
belongs_to :account, :class_name => 'User'
|
20
20
|
scope :recent, :url => 'comments/recent'
|
21
|
-
|
22
21
|
custom_urls :by_user_url => 'comments/by_user/:name'
|
23
22
|
end
|
24
23
|
|
24
|
+
class CustomRootComment < Comment
|
25
|
+
def self.json_root
|
26
|
+
'custom'
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
25
30
|
class User < MotionResource::Base
|
26
31
|
self.member_url = 'users/:id'
|
27
32
|
|
@@ -91,6 +91,21 @@ describe "belongs_to" do
|
|
91
91
|
@response.should.be.ok
|
92
92
|
end
|
93
93
|
end
|
94
|
+
|
95
|
+
it "should return correct type of object" do
|
96
|
+
stub_request(:get, "http://example.com/users/1.json").to_return(json: { id: 1, text: 'Hello' })
|
97
|
+
@comment = Comment.new(:account_id => 1)
|
98
|
+
@comment.account do |results, response|
|
99
|
+
@account = results
|
100
|
+
@response = response
|
101
|
+
resume
|
102
|
+
end
|
103
|
+
wait_max 1.0 do
|
104
|
+
@response.should.be.ok
|
105
|
+
@account.class.should == User
|
106
|
+
end
|
107
|
+
end
|
108
|
+
|
94
109
|
end
|
95
110
|
|
96
111
|
describe "writer" do
|
@@ -99,11 +114,18 @@ describe "belongs_to" do
|
|
99
114
|
comment.post = { :id => 1, :text => 'Hello' }
|
100
115
|
comment.post.should.is_a Post
|
101
116
|
end
|
117
|
+
|
118
|
+
it "should convert hash to proper type" do
|
119
|
+
comment = Comment.new
|
120
|
+
comment.account = { :id => 1, :text => 'Hello' }
|
121
|
+
comment.account.class.should == User
|
122
|
+
end
|
102
123
|
|
103
124
|
it "should set attributes when assigned with hash" do
|
104
125
|
comment = Comment.new
|
105
126
|
comment.post = { :id => 1, :text => 'Hello' }
|
106
127
|
comment.post.text.should == 'Hello'
|
128
|
+
comment.post.class.should == Post
|
107
129
|
end
|
108
130
|
|
109
131
|
it "should use identity map when assigned with hash" do
|
@@ -119,6 +141,18 @@ describe "belongs_to" do
|
|
119
141
|
comment.post = post
|
120
142
|
comment.post.should == post
|
121
143
|
end
|
144
|
+
|
145
|
+
it "should set association id when assigned with hash" do
|
146
|
+
comment = Comment.new
|
147
|
+
comment.post = { :id => 10 }
|
148
|
+
comment.post_id.should == 10
|
149
|
+
end
|
150
|
+
|
151
|
+
it "should set association id when assigned with object" do
|
152
|
+
comment = Comment.new
|
153
|
+
comment.post = Post.new(:id => 10)
|
154
|
+
comment.post_id.should == 10
|
155
|
+
end
|
122
156
|
end
|
123
157
|
|
124
158
|
describe "piggybacking" do
|
@@ -65,5 +65,15 @@ describe "base" do
|
|
65
65
|
shape1.should.be.identical_to shape2
|
66
66
|
shape1.contents.should == 'something'
|
67
67
|
end
|
68
|
+
|
69
|
+
it "should instantiate with ID number" do
|
70
|
+
shape = Shape.instantiate(3)
|
71
|
+
shape.id.should == 3
|
72
|
+
end
|
73
|
+
|
74
|
+
it "should instantiate with ID string" do
|
75
|
+
shape = Shape.instantiate("5")
|
76
|
+
shape.id.should == 5
|
77
|
+
end
|
68
78
|
end
|
69
79
|
end
|
@@ -65,6 +65,35 @@ describe "crud" do
|
|
65
65
|
@response.should.not.be.ok
|
66
66
|
end
|
67
67
|
end
|
68
|
+
|
69
|
+
it "should include association" do
|
70
|
+
stub_request(:post, "http://example.com/posts.json").to_return(body: "")
|
71
|
+
Post.new.create(:include => :comments) do |result, response|
|
72
|
+
@response = response
|
73
|
+
resume
|
74
|
+
end
|
75
|
+
|
76
|
+
wait_max 1.0 do
|
77
|
+
@response.should.be.ok
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
it "should include association with _attributes suffix" do
|
82
|
+
stub_request(:post, "http://example.com/posts.json").to_return(body: "")
|
83
|
+
Post.new.create(:include => :comments_attributes) do |result, response|
|
84
|
+
@response = response
|
85
|
+
resume
|
86
|
+
end
|
87
|
+
|
88
|
+
wait_max 1.0 do
|
89
|
+
@response.should.be.ok
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
it "should raise error when included association is not found" do
|
94
|
+
stub_request(:post, "http://example.com/posts.json").to_return(body: "")
|
95
|
+
lambda { Post.new.create(:include => :foobar) { |result, response| } }.should.raise(ArgumentError)
|
96
|
+
end
|
68
97
|
end
|
69
98
|
|
70
99
|
describe "update" do
|
@@ -131,6 +160,19 @@ describe "crud" do
|
|
131
160
|
@response.should.not.be.ok
|
132
161
|
end
|
133
162
|
end
|
163
|
+
|
164
|
+
|
165
|
+
it "should include association" do
|
166
|
+
stub_request(:put, "http://example.com/posts/10.json").to_return(body: "")
|
167
|
+
Post.instantiate(:id => 10).update(:include => :comments) do |result, response|
|
168
|
+
@response = response
|
169
|
+
resume
|
170
|
+
end
|
171
|
+
|
172
|
+
wait_max 1.0 do
|
173
|
+
@response.should.be.ok
|
174
|
+
end
|
175
|
+
end
|
134
176
|
end
|
135
177
|
|
136
178
|
describe "destroy" do
|
@@ -76,6 +76,20 @@ describe "find" do
|
|
76
76
|
end
|
77
77
|
end
|
78
78
|
|
79
|
+
it "should allow hash JSON response with custom JSON root" do
|
80
|
+
stub_request(:get, "http://example.com/bar.json").to_return(json: { custom: [{ id: 10, text: '42' }] })
|
81
|
+
CustomRootComment.fetch_collection("bar") do |result|
|
82
|
+
@result = result
|
83
|
+
resume
|
84
|
+
end
|
85
|
+
|
86
|
+
wait_max 1.0 do
|
87
|
+
@result.should.is_a Array
|
88
|
+
@result.first.should.is_a CustomRootComment
|
89
|
+
@result.first.text.should == '42'
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
79
93
|
it "should give nil object if fetching collection fails" do
|
80
94
|
stub_request(:get, "http://example.com/bar.json").to_return(status_code: 404)
|
81
95
|
Comment.fetch_collection("bar") do |result|
|
@@ -120,7 +120,8 @@ describe "requests" do
|
|
120
120
|
it "should call a block given to on_auth_failure on 401" do
|
121
121
|
stub_request(:get, "http://example.com/comments/10.json").to_return(status_code: 401)
|
122
122
|
@fail = false
|
123
|
-
Comment.on_auth_failure { @fail = true
|
123
|
+
Comment.on_auth_failure { @fail = true }
|
124
|
+
|
124
125
|
Comment.new.get("comments/10") do |response, json|
|
125
126
|
resume
|
126
127
|
end
|
@@ -2,34 +2,38 @@ class DelegateObject
|
|
2
2
|
attr_accessor :id, :name
|
3
3
|
end
|
4
4
|
|
5
|
-
describe "
|
5
|
+
describe "url encoder" do
|
6
|
+
before do
|
7
|
+
@encoder = MotionResource::Base.url_encoder
|
8
|
+
end
|
9
|
+
|
6
10
|
it "should fill url params from params hash" do
|
7
|
-
string = "accounts/:id/users/:name"
|
11
|
+
string = @encoder.fill_url_params("accounts/:id/users/:name", {id: 10, name: 'john'})
|
8
12
|
string.should == "accounts/10/users/john"
|
9
13
|
end
|
10
14
|
|
11
15
|
it "should insert an extension if missing" do
|
12
|
-
string = "accounts/fabulous"
|
16
|
+
string = @encoder.insert_extension("accounts/fabulous",".json")
|
13
17
|
string.should == "accounts/fabulous.json"
|
14
18
|
end
|
15
19
|
|
16
20
|
it "should not insert extension if it is blank" do
|
17
|
-
string = "accounts/fabulous"
|
21
|
+
string = @encoder.insert_extension("accounts/fabulous","")
|
18
22
|
string.should == "accounts/fabulous"
|
19
23
|
end
|
20
24
|
|
21
25
|
it "should add a query string for non-url params" do
|
22
|
-
string = "accounts/fabulous"
|
26
|
+
string = @encoder.build_query_string("accounts/fabulous", {foo: 10, moo: "rar"})
|
23
27
|
string.should == "accounts/fabulous?foo=10&moo=rar"
|
24
28
|
end
|
25
29
|
|
26
30
|
it "should not add a ? when building a query string if it exists" do
|
27
|
-
string = "accounts/fabulous?"
|
31
|
+
string = @encoder.build_query_string("accounts/fabulous?", {foo: 10, moo: "rar"})
|
28
32
|
string.should == "accounts/fabulous?foo=10&moo=rar"
|
29
33
|
end
|
30
34
|
|
31
35
|
it "should tag new query params onto existing ones" do
|
32
|
-
string = "accounts/fabulous?moo=rar"
|
36
|
+
string = @encoder.build_query_string("accounts/fabulous?moo=rar", {foo: 10})
|
33
37
|
string.should == "accounts/fabulous?moo=rar&foo=10"
|
34
38
|
end
|
35
39
|
|
@@ -37,15 +41,15 @@ describe "String" do
|
|
37
41
|
obj = DelegateObject.new
|
38
42
|
obj.id = 10
|
39
43
|
obj.name = 'john'
|
40
|
-
string = "accounts/:id/users/:name"
|
44
|
+
string = @encoder.fill_url_params("accounts/:id/users/:name", {}, obj)
|
41
45
|
string.should == "accounts/10/users/john"
|
42
46
|
end
|
43
47
|
|
44
48
|
it "should not crash when a param is unknown" do
|
45
|
-
lambda { "accounts/:id"
|
49
|
+
lambda { @encoder.fill_url_params("accounts/:id", {}) }.should.not.raise
|
46
50
|
end
|
47
51
|
|
48
52
|
it "should not crash when params hash contains an unused value" do
|
49
|
-
lambda { "accounts"
|
53
|
+
lambda { @encoder.fill_url_params("accounts", {foo:'bar'}) }.should.not.raise
|
50
54
|
end
|
51
55
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: motion-resource
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.4
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2013-
|
12
|
+
date: 2013-07-16 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: bubble-wrap
|
@@ -90,7 +90,7 @@ files:
|
|
90
90
|
- lib/motion-resource/logger.rb
|
91
91
|
- lib/motion-resource/requests.rb
|
92
92
|
- lib/motion-resource/spec_helpers.rb
|
93
|
-
- lib/motion-resource/
|
93
|
+
- lib/motion-resource/url_encoder.rb
|
94
94
|
- lib/motion-resource/urls.rb
|
95
95
|
- lib/motion-resource/version.rb
|
96
96
|
- motion-resource.gemspec
|
@@ -105,7 +105,7 @@ files:
|
|
105
105
|
- spec/motion-resource/crud_spec.rb
|
106
106
|
- spec/motion-resource/find_spec.rb
|
107
107
|
- spec/motion-resource/requests_spec.rb
|
108
|
-
- spec/motion-resource/
|
108
|
+
- spec/motion-resource/url_encoder_spec.rb
|
109
109
|
- spec/motion-resource/urls_spec.rb
|
110
110
|
homepage: https://github.com/tkadauke/motion-resource
|
111
111
|
licenses: []
|
@@ -121,7 +121,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
121
121
|
version: '0'
|
122
122
|
segments:
|
123
123
|
- 0
|
124
|
-
hash:
|
124
|
+
hash: 3639631242463817566
|
125
125
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
126
126
|
none: false
|
127
127
|
requirements:
|
@@ -130,7 +130,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
130
130
|
version: '0'
|
131
131
|
segments:
|
132
132
|
- 0
|
133
|
-
hash:
|
133
|
+
hash: 3639631242463817566
|
134
134
|
requirements: []
|
135
135
|
rubyforge_project:
|
136
136
|
rubygems_version: 1.8.25
|
@@ -149,5 +149,5 @@ test_files:
|
|
149
149
|
- spec/motion-resource/crud_spec.rb
|
150
150
|
- spec/motion-resource/find_spec.rb
|
151
151
|
- spec/motion-resource/requests_spec.rb
|
152
|
-
- spec/motion-resource/
|
152
|
+
- spec/motion-resource/url_encoder_spec.rb
|
153
153
|
- spec/motion-resource/urls_spec.rb
|
@@ -1,46 +0,0 @@
|
|
1
|
-
class String
|
2
|
-
# Takes in a hash and spits out the formatted string
|
3
|
-
# Checks the delegate first
|
4
|
-
def fill_url_params(params = {}, delegate = nil)
|
5
|
-
params ||= {}
|
6
|
-
split = self.split '/'
|
7
|
-
url = split.collect { |path|
|
8
|
-
ret = path
|
9
|
-
if path[0] == ':'
|
10
|
-
path_sym = path[1..-1].to_sym
|
11
|
-
|
12
|
-
curr = nil
|
13
|
-
if delegate && delegate.respond_to?(path_sym)
|
14
|
-
curr = delegate.send(path_sym)
|
15
|
-
end
|
16
|
-
|
17
|
-
ret = (curr || params.delete(path_sym) || path).to_s
|
18
|
-
end
|
19
|
-
|
20
|
-
ret
|
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.to_query
|
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
|
45
|
-
end
|
46
|
-
end
|