api-client 2.0.0.rc1 → 2.0.0.rc2
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +2 -0
- data/CHANGELOG.md +11 -5
- data/Gemfile +1 -1
- data/Rakefile +3 -3
- data/api-client.gemspec +9 -9
- data/examples/config/initializers/api-client.rb +1 -1
- data/examples/controllers/application_controller.rb +3 -3
- data/examples/controllers/user_controller.rb +2 -2
- data/examples/models/admin.rb +2 -2
- data/examples/models/group.rb +1 -1
- data/examples/models/user.rb +1 -1
- data/gemfiles/Gemfile.typhoeus +3 -1
- data/lib/api-client.rb +1 -1
- data/lib/api-client/base.rb +23 -10
- data/lib/api-client/class_methods.rb +11 -1
- data/lib/api-client/collection.rb +2 -2
- data/lib/api-client/configuration.rb +3 -3
- data/lib/api-client/dispatcher.rb +12 -1
- data/lib/api-client/dispatcher/net-http.rb +2 -2
- data/lib/api-client/errors.rb +7 -3
- data/lib/api-client/exceptions.rb +1 -1
- data/lib/api-client/exceptions/bad_gateway.rb +1 -1
- data/lib/api-client/exceptions/connection_refused.rb +1 -1
- data/lib/api-client/exceptions/forbidden.rb +1 -1
- data/lib/api-client/exceptions/generic.rb +1 -1
- data/lib/api-client/exceptions/internal_server_error.rb +1 -1
- data/lib/api-client/exceptions/not_configured.rb +2 -2
- data/lib/api-client/exceptions/service_unavailable.rb +1 -1
- data/lib/api-client/exceptions/unauthorized.rb +1 -1
- data/lib/api-client/instance_methods.rb +11 -1
- data/lib/api-client/parser.rb +2 -1
- data/lib/api-client/version.rb +2 -2
- data/spec/api-client/base_spec.rb +84 -60
- data/spec/api-client/collection_spec.rb +5 -5
- data/spec/api-client/configuration_spec.rb +13 -13
- data/spec/api-client/dispatcher_spec.rb +16 -16
- data/spec/api-client/errors_spec.rb +8 -8
- data/spec/api-client/parser_spec.rb +27 -27
- data/spec/spec_helper.rb +8 -8
- metadata +19 -4
data/.gitignore
CHANGED
data/CHANGELOG.md
CHANGED
@@ -1,20 +1,26 @@
|
|
1
1
|
# CHANGELOG
|
2
2
|
|
3
|
+
## v2.0.0.rc1
|
4
|
+
|
5
|
+
* Add Support for global url.
|
6
|
+
* Add Support for instance requests.
|
7
|
+
* Changed behavior of request methods to only accepts the resource id if needed..
|
8
|
+
|
3
9
|
## v1.10.0
|
4
10
|
|
5
|
-
* Add Support for api responses with collections
|
11
|
+
* Add Support for api responses with collections.
|
6
12
|
|
7
13
|
## v1.9.1
|
8
14
|
|
9
|
-
* Fix for Net::Http on NotFound Exception
|
15
|
+
* Fix for Net::Http on NotFound Exception.
|
10
16
|
|
11
17
|
## v1.9.0
|
12
18
|
|
13
|
-
* Added Requested Url to NotFound Exception message
|
19
|
+
* Added Requested Url to NotFound Exception message.
|
14
20
|
|
15
21
|
## v1.8.2
|
16
22
|
|
17
|
-
* Fixed Query String Bug (It was been sent empty)
|
23
|
+
* Fixed Query String Bug (It was been sent empty).
|
18
24
|
|
19
25
|
## v1.8.1
|
20
26
|
|
@@ -105,4 +111,4 @@
|
|
105
111
|
## v0.0.1
|
106
112
|
|
107
113
|
* get method added.
|
108
|
-
* handler for response code 404 added.
|
114
|
+
* handler for response code 404 added.
|
data/Gemfile
CHANGED
data/Rakefile
CHANGED
data/api-client.gemspec
CHANGED
@@ -2,7 +2,7 @@
|
|
2
2
|
require File.expand_path('../lib/api-client/version', __FILE__)
|
3
3
|
|
4
4
|
Gem::Specification.new do |gem|
|
5
|
-
gem.name =
|
5
|
+
gem.name = 'api-client'
|
6
6
|
gem.version = ApiClient::VERSION
|
7
7
|
gem.authors = %q{Paulo Henrique Lopes Ribeiro}
|
8
8
|
gem.email = %q{plribeiro3000@gmail.com}
|
@@ -13,12 +13,12 @@ Gem::Specification.new do |gem|
|
|
13
13
|
gem.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
14
14
|
gem.require_paths = %w(lib)
|
15
15
|
|
16
|
-
gem.add_development_dependency
|
17
|
-
gem.add_development_dependency
|
18
|
-
gem.add_development_dependency
|
19
|
-
gem.add_development_dependency
|
20
|
-
gem.add_development_dependency
|
16
|
+
gem.add_development_dependency 'rake'
|
17
|
+
gem.add_development_dependency 'webmock'
|
18
|
+
gem.add_development_dependency 'rspec'
|
19
|
+
gem.add_development_dependency 'yard'
|
20
|
+
gem.add_development_dependency 'coveralls'
|
21
21
|
|
22
|
-
gem.add_runtime_dependency
|
23
|
-
gem.add_runtime_dependency
|
24
|
-
end
|
22
|
+
gem.add_runtime_dependency 'activemodel'
|
23
|
+
gem.add_runtime_dependency 'json_pure'
|
24
|
+
end
|
@@ -15,11 +15,11 @@ class ApplicationController < ActionController::Base
|
|
15
15
|
|
16
16
|
def not_found
|
17
17
|
ApplicationMailer.send_not_found_notice.deliver
|
18
|
-
render :file =>
|
18
|
+
render :file => '/public/404.html', :status => 404
|
19
19
|
end
|
20
20
|
|
21
21
|
def generic(exception)
|
22
22
|
ApplicationMailer.send_generic_error(exception).deliver
|
23
|
-
render :file =>
|
23
|
+
render :file => '/public/404.html', :status => 404
|
24
24
|
end
|
25
|
-
end
|
25
|
+
end
|
@@ -15,7 +15,7 @@ class UserController < ApplicationController
|
|
15
15
|
|
16
16
|
# It will hit http://api.example.com/users with a post request
|
17
17
|
def create
|
18
|
-
@user = User.post(
|
18
|
+
@user = User.post('', :user => params[:user])
|
19
19
|
respond_with(@user)
|
20
20
|
end
|
21
21
|
|
@@ -27,7 +27,7 @@ class UserController < ApplicationController
|
|
27
27
|
|
28
28
|
# It will hit http://api.example.com/users/1 with a patch request
|
29
29
|
def update
|
30
|
-
@user = User.patch(
|
30
|
+
@user = User.patch(params[:id], { :user => params[:user] })
|
31
31
|
respond_with(@user)
|
32
32
|
end
|
33
33
|
|
data/examples/models/admin.rb
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
class Admin < ApiClient::Base
|
2
|
-
self.remote_object =
|
3
|
-
self.association = { :groups =>
|
2
|
+
self.remote_object = 'user'
|
3
|
+
self.association = { :groups => 'Group' }
|
4
4
|
|
5
5
|
# Any of this fields can be called to manage rails form.
|
6
6
|
attr_accessor :id, :email, :password, :password_confirmation
|
data/examples/models/group.rb
CHANGED
data/examples/models/user.rb
CHANGED
data/gemfiles/Gemfile.typhoeus
CHANGED
data/lib/api-client.rb
CHANGED
data/lib/api-client/base.rb
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
require
|
1
|
+
require 'active_model'
|
2
2
|
|
3
3
|
module ApiClient
|
4
4
|
# ApiClient::Base provides a way to make easy api requests as well as making possible to use it inside rails.
|
@@ -27,7 +27,7 @@ module ApiClient
|
|
27
27
|
# @return [Base] the object initialized.
|
28
28
|
def initialize(attributes = {})
|
29
29
|
@errors = ApiClient::Errors.new(self)
|
30
|
-
attributes.each do |name, value|
|
30
|
+
remove_root(attributes).each do |name, value|
|
31
31
|
send("#{name.to_s}=", value)
|
32
32
|
end
|
33
33
|
end
|
@@ -43,7 +43,7 @@ module ApiClient
|
|
43
43
|
#
|
44
44
|
# @return [String] the api path for this object.
|
45
45
|
def self.path
|
46
|
-
return self.to_s.gsub(
|
46
|
+
return self.to_s.gsub('::', '/').downcase.pluralize unless @path
|
47
47
|
@path
|
48
48
|
end
|
49
49
|
|
@@ -51,7 +51,7 @@ module ApiClient
|
|
51
51
|
#
|
52
52
|
# @param [String] path string.
|
53
53
|
def self.path=(path)
|
54
|
-
path = path[1, path.size - 1] if path[0, 1] ==
|
54
|
+
path = path[1, path.size - 1] if path[0, 1] == '/'
|
55
55
|
@path = path
|
56
56
|
end
|
57
57
|
|
@@ -76,7 +76,12 @@ module ApiClient
|
|
76
76
|
associations.each do |association, class_name|
|
77
77
|
class_eval <<-EVAL
|
78
78
|
def #{association.to_s}=(attributes = {})
|
79
|
-
|
79
|
+
if attributes.instance_of?(Array)
|
80
|
+
return @#{association.to_s} = attributes.map { |attr|
|
81
|
+
attr = remove_root(attr)
|
82
|
+
#{class_name.constantize}.new(attr)
|
83
|
+
}
|
84
|
+
end
|
80
85
|
@#{association.to_s} = #{class_name.constantize}.new(attributes)
|
81
86
|
end
|
82
87
|
def #{association.to_s}
|
@@ -99,18 +104,18 @@ module ApiClient
|
|
99
104
|
super
|
100
105
|
end
|
101
106
|
|
102
|
-
# Return an array with all instance variables setted through
|
107
|
+
# Return an array with all instance variables setted through attr_accessor.
|
103
108
|
#
|
104
109
|
# @return [Array] instance variables.
|
105
110
|
def self.attributes
|
106
111
|
@attributes
|
107
112
|
end
|
108
113
|
|
109
|
-
# Return an array with all instance variables setted through
|
114
|
+
# Return an array with all instance variables setted through attr_accessor and its currently values.
|
110
115
|
#
|
111
116
|
# @return [Hash] instance variables and its values.
|
112
117
|
def attributes
|
113
|
-
self.class.instance_variable_get(
|
118
|
+
self.class.instance_variable_get('@attributes').inject({}) { |hash, attribute| hash.merge(attribute.to_sym => self.send("#{attribute}")) }
|
114
119
|
end
|
115
120
|
|
116
121
|
alias_method :to_hash, :attributes
|
@@ -126,9 +131,17 @@ module ApiClient
|
|
126
131
|
|
127
132
|
# Set the hash of errors, making keys symbolic.
|
128
133
|
#
|
129
|
-
# @param [Hash] errors of the object.
|
134
|
+
# @param [Hash] errs errors of the object.
|
130
135
|
def errors=(errs = {})
|
131
136
|
errors.add_errors(Hash[errs.map{|(key,value)| [key.to_sym,value]}])
|
132
137
|
end
|
138
|
+
|
139
|
+
protected
|
140
|
+
|
141
|
+
def remove_root(attributes = {})
|
142
|
+
attributes = attributes[self.class.remote_object.to_sym] if attributes.key?(self.class.remote_object.to_sym)
|
143
|
+
attributes = attributes[self.class.remote_object.to_s] if attributes.key?(self.class.remote_object.to_s)
|
144
|
+
attributes
|
145
|
+
end
|
133
146
|
end
|
134
|
-
end
|
147
|
+
end
|
@@ -3,7 +3,7 @@ module ApiClient
|
|
3
3
|
module ClassMethods
|
4
4
|
# Initialize an object based on a hash of attributes.
|
5
5
|
#
|
6
|
-
# @param [Hash]
|
6
|
+
# @param [Hash] params hash of attributes.
|
7
7
|
# @return [Base] the object initialized.
|
8
8
|
def build(params)
|
9
9
|
if params.key?(remote_object)
|
@@ -26,5 +26,15 @@ module ApiClient
|
|
26
26
|
params = ApiClient::Parser.response(response, url)
|
27
27
|
build(params)
|
28
28
|
end
|
29
|
+
|
30
|
+
# Overwrite respond_to? default behavior
|
31
|
+
#
|
32
|
+
# @param [Symbol] method_name the name of the method.
|
33
|
+
# @param [Boolean] include_private if it does work to private methods as well.
|
34
|
+
# @return [Boolean] if it responds to the method or not.
|
35
|
+
def respond_to_missing?(method_name, include_private = false)
|
36
|
+
return true if ApiClient::Dispatcher.respond_to?(method_name)
|
37
|
+
super
|
38
|
+
end
|
29
39
|
end
|
30
40
|
end
|
@@ -6,8 +6,8 @@ class ApiClient::Collection
|
|
6
6
|
|
7
7
|
# Initialize a collection of given objects
|
8
8
|
#
|
9
|
-
# @param [Class] The class to instantiate the objects.
|
10
|
-
# @param [String] The url to get the data.
|
9
|
+
# @param [Class] klass The class to instantiate the objects.
|
10
|
+
# @param [String] resource_path The url to get the data.
|
11
11
|
# @return [Collection] the collection of objects.
|
12
12
|
def initialize(klass, resource_path)
|
13
13
|
url = "#{ApiClient.config.path}#{resource_path}"
|
@@ -11,10 +11,10 @@ module ApiClient
|
|
11
11
|
|
12
12
|
# Set the api url.
|
13
13
|
#
|
14
|
-
# @param [String] api url.
|
14
|
+
# @param [String] path api url.
|
15
15
|
def path=(path)
|
16
|
-
path = "#{path}/" unless path[path.size - 1, 1] ==
|
16
|
+
path = "#{path}/" unless path[path.size - 1, 1] == '/'
|
17
17
|
@path = path
|
18
18
|
end
|
19
19
|
end
|
20
|
-
end
|
20
|
+
end
|
@@ -10,4 +10,15 @@ module ApiClient::Dispatcher
|
|
10
10
|
NetHttp.send(method, *args)
|
11
11
|
end
|
12
12
|
end
|
13
|
-
|
13
|
+
|
14
|
+
# Overwrite respond_to? default behavior
|
15
|
+
#
|
16
|
+
# @param [Symbol] method_name the name of the method.
|
17
|
+
# @param [Boolean] include_private if it does work to private methods as well.
|
18
|
+
# @return [Boolean] if it responds to the method or not.
|
19
|
+
def respond_to_missing?(method_name, include_private = false)
|
20
|
+
return true if Typhoeus.respond_to?(method_name)
|
21
|
+
return true if NetHttp.respond_to?(method_name)
|
22
|
+
super
|
23
|
+
end
|
24
|
+
end
|
@@ -1,5 +1,5 @@
|
|
1
|
-
require
|
2
|
-
require
|
1
|
+
require 'net/http'
|
2
|
+
require 'api-client/net/http' unless Net::HTTP.new('').respond_to?(:patch)
|
3
3
|
|
4
4
|
# ApiClient::Dispatcher provides methods to make requests using the native ruby library 'net/http'
|
5
5
|
module ApiClient::Dispatcher::NetHttp
|
data/lib/api-client/errors.rb
CHANGED
@@ -1,9 +1,10 @@
|
|
1
|
-
require
|
1
|
+
require 'active_model'
|
2
2
|
|
3
3
|
# ApiClient::Errors provide extra functionality to ActiveModel::Errors.
|
4
4
|
class ApiClient::Errors < ActiveModel::Errors
|
5
|
-
# Add
|
5
|
+
# Add several errors from a hash to the object.
|
6
6
|
#
|
7
|
+
# @param [Hash] errors The hash with errors to add.
|
7
8
|
# @return [ApiClient::Errors] The Error object.
|
8
9
|
def add_errors(errors = {})
|
9
10
|
errors.each_pair do |key, value|
|
@@ -21,6 +22,7 @@ class ApiClient::Errors < ActiveModel::Errors
|
|
21
22
|
# person = Person.create(address: '123 First St.')
|
22
23
|
# person.errors.unique_messages
|
23
24
|
# # => { :name => "is too short (minimum is 5 characters) and can't be blank", :address => nil, :email => "can't be blank" }
|
25
|
+
# @return [Hash] A hash with all the errors joined by attribute.
|
24
26
|
def unique_messages
|
25
27
|
errors = {}
|
26
28
|
map { |attribute, messages| errors[attribute] = unique_message(attribute) }
|
@@ -37,8 +39,10 @@ class ApiClient::Errors < ActiveModel::Errors
|
|
37
39
|
# person = Person.create(address: '123 First St.')
|
38
40
|
# person.errors.unique_message(:name) # => "is too short (minimum is 5 characters) and can't be blank"
|
39
41
|
# person.errors.unique_message(:address) # => nil
|
42
|
+
# @param [String] attribute The attribute to check for joined error messages.
|
43
|
+
# @return [String] A string with all errors from the given attribute joined.
|
40
44
|
def unique_message(attribute)
|
41
45
|
return '' if messages[attribute].blank?
|
42
46
|
[messages[attribute]].flatten.to_sentence
|
43
47
|
end
|
44
|
-
end
|
48
|
+
end
|
@@ -3,7 +3,7 @@ module ApiClient
|
|
3
3
|
module InstanceMethods
|
4
4
|
# Update an object based on a hash of attributes.
|
5
5
|
#
|
6
|
-
# @param [Hash]
|
6
|
+
# @param [Hash] params hash of attributes.
|
7
7
|
# @return [Base] the updated object.
|
8
8
|
def update(params)
|
9
9
|
if params.key?(self.class.remote_object)
|
@@ -33,5 +33,15 @@ module ApiClient
|
|
33
33
|
params = ApiClient::Parser.response(response, url)
|
34
34
|
update(params)
|
35
35
|
end
|
36
|
+
|
37
|
+
# Overwrite respond_to? default behavior
|
38
|
+
#
|
39
|
+
# @param [Symbol] method_name the name of the method.
|
40
|
+
# @param [Boolean] include_private if it does work to private methods as well.
|
41
|
+
# @return [Boolean] if it responds to the method or not.
|
42
|
+
def respond_to_missing?(method_name, include_private = false)
|
43
|
+
return true if ApiClient::Dispatcher.respond_to?(method_name)
|
44
|
+
super
|
45
|
+
end
|
36
46
|
end
|
37
47
|
end
|
data/lib/api-client/parser.rb
CHANGED
@@ -5,6 +5,7 @@ module ApiClient::Parser
|
|
5
5
|
# Parse the JSON response.
|
6
6
|
#
|
7
7
|
# @param [HTTP] response HTTP object for the request.
|
8
|
+
# @param [String] url The url of the requisition.
|
8
9
|
# @return [Hash] the body parsed.
|
9
10
|
def self.response(response, url)
|
10
11
|
raise_exception(response, url)
|
@@ -29,4 +30,4 @@ module ApiClient::Parser
|
|
29
30
|
else return
|
30
31
|
end
|
31
32
|
end
|
32
|
-
end
|
33
|
+
end
|
data/lib/api-client/version.rb
CHANGED
@@ -4,167 +4,191 @@ describe ApiClient::Base do
|
|
4
4
|
let(:user) { User.new }
|
5
5
|
let(:collection) { Object.new }
|
6
6
|
|
7
|
-
describe
|
7
|
+
describe '.initialize' do
|
8
8
|
context "with a hash {:a => 'a', :b => 'b'}" do
|
9
9
|
before :each do
|
10
|
-
@user = User.new({:a =>
|
10
|
+
@user = User.new({:a => 'a', :b => 'b'})
|
11
11
|
end
|
12
12
|
|
13
|
-
it
|
14
|
-
@user.a.should ==
|
13
|
+
it 'should set #a' do
|
14
|
+
@user.a.should == 'a'
|
15
15
|
end
|
16
16
|
|
17
|
-
it
|
18
|
-
@user.b.should ==
|
17
|
+
it 'should set #b' do
|
18
|
+
@user.b.should == 'b'
|
19
19
|
end
|
20
20
|
|
21
|
-
it
|
21
|
+
it 'should initialize errors' do
|
22
22
|
@user.errors.should be_an_instance_of(ApiClient::Errors)
|
23
23
|
end
|
24
24
|
end
|
25
|
+
|
26
|
+
context "with a hash with string keys {'a' => 'a', 'b' => 'b' }" do
|
27
|
+
before :each do
|
28
|
+
@user = User.new({ 'user' => { 'a' => 'a', "b" => "b" } })
|
29
|
+
end
|
30
|
+
|
31
|
+
it 'should initialize attributes' do
|
32
|
+
@user.attributes.should == { :a => 'a', :b => 'b' }
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
context 'with a root node' do
|
37
|
+
before :each do
|
38
|
+
@user = User.new({ :user => { :a => 'a', :b => 'b' } })
|
39
|
+
end
|
40
|
+
|
41
|
+
it 'should initialize attributes' do
|
42
|
+
@user.attributes.should == { :a => 'a', :b => 'b' }
|
43
|
+
end
|
44
|
+
end
|
25
45
|
end
|
26
46
|
|
27
|
-
describe
|
28
|
-
describe
|
29
|
-
it
|
30
|
-
User.path.should ==
|
47
|
+
describe '.path' do
|
48
|
+
describe 'when not configured' do
|
49
|
+
it 'should return a name based on the class name' do
|
50
|
+
User.path.should == 'users'
|
31
51
|
end
|
32
52
|
end
|
33
53
|
|
34
|
-
describe
|
54
|
+
describe 'when properly configured' do
|
35
55
|
before :each do
|
36
|
-
User.path =
|
56
|
+
User.path = 'admins'
|
37
57
|
end
|
38
58
|
|
39
|
-
it
|
40
|
-
User.path.should ==
|
59
|
+
it 'should return the path value' do
|
60
|
+
User.path.should == 'admins'
|
41
61
|
end
|
42
62
|
end
|
43
63
|
end
|
44
64
|
|
45
|
-
describe
|
65
|
+
describe '.path=' do
|
46
66
|
describe "with a string without '/'" do
|
47
67
|
before :each do
|
48
|
-
User.path =
|
68
|
+
User.path = 'users'
|
49
69
|
end
|
50
70
|
|
51
|
-
it
|
52
|
-
User.path.should ==
|
71
|
+
it 'should set it as passed' do
|
72
|
+
User.path.should == 'users'
|
53
73
|
end
|
54
74
|
end
|
55
75
|
|
56
76
|
describe "with a string with '/'" do
|
57
77
|
before :each do
|
58
|
-
User.path =
|
78
|
+
User.path = '/users'
|
59
79
|
end
|
60
80
|
|
61
81
|
it "should set it without the '/'" do
|
62
|
-
User.path.should ==
|
82
|
+
User.path.should == 'users'
|
63
83
|
end
|
64
84
|
end
|
65
85
|
end
|
66
86
|
|
67
|
-
describe
|
68
|
-
context
|
69
|
-
it
|
70
|
-
User.remote_object.should ==
|
87
|
+
describe '.remote_object' do
|
88
|
+
context 'on a class without remote object specification' do
|
89
|
+
it 'should return the class name' do
|
90
|
+
User.remote_object.should == 'user'
|
71
91
|
end
|
72
92
|
end
|
73
93
|
|
74
|
-
context
|
75
|
-
it
|
76
|
-
Admin.remote_object.should ==
|
94
|
+
context 'on a class with remote object specification' do
|
95
|
+
it 'should return the class name' do
|
96
|
+
Admin.remote_object.should == 'user'
|
77
97
|
end
|
78
98
|
end
|
79
99
|
end
|
80
100
|
|
81
|
-
describe
|
82
|
-
it
|
83
|
-
Admin.remote_object.should ==
|
101
|
+
describe '.remote_object=' do
|
102
|
+
it 'should set the remote object name' do
|
103
|
+
Admin.remote_object.should == 'user'
|
84
104
|
end
|
85
105
|
end
|
86
106
|
|
87
|
-
describe
|
88
|
-
it
|
107
|
+
describe '#persisted?' do
|
108
|
+
it 'should return false' do
|
89
109
|
User.new.should_not be_persisted
|
90
110
|
end
|
91
111
|
end
|
92
112
|
|
93
|
-
describe
|
113
|
+
describe '.associations=' do
|
94
114
|
before :each do
|
95
|
-
@group = Group.new(:members => [{:a =>
|
115
|
+
@group = Group.new(:members => [ :user => {:a => 'a'}], :owner => {:b => 'b'})
|
116
|
+
end
|
117
|
+
|
118
|
+
it 'should instantiate a collection of members' do
|
119
|
+
@group.members.should be_an_instance_of(Array)
|
96
120
|
end
|
97
121
|
|
98
|
-
it
|
122
|
+
it 'should instantiate the member' do
|
99
123
|
@group.members.first.should be_an_instance_of(User)
|
100
124
|
end
|
101
125
|
|
102
|
-
it
|
126
|
+
it 'should instantiate the owner' do
|
103
127
|
@group.owner.should be_an_instance_of(Admin)
|
104
128
|
end
|
105
129
|
end
|
106
130
|
|
107
|
-
describe
|
108
|
-
it
|
131
|
+
describe '.attributes' do
|
132
|
+
it 'should return an array of attributes' do
|
109
133
|
User.attributes.should == [:a, :b]
|
110
134
|
end
|
111
135
|
end
|
112
136
|
|
113
|
-
describe
|
114
|
-
it
|
115
|
-
User.new.attributes.should == {:a => nil, :b => nil}
|
137
|
+
describe '#attributes' do
|
138
|
+
it 'should return a hash with the attributes and currently values' do
|
139
|
+
User.new.attributes.should == { :a => nil, :b => nil }
|
116
140
|
end
|
117
141
|
end
|
118
142
|
|
119
|
-
describe
|
143
|
+
describe '.collection' do
|
120
144
|
before :each do
|
121
|
-
ApiClient::Collection.stub(:new).with(User,
|
145
|
+
ApiClient::Collection.stub(:new).with(User, 'users').and_return(collection)
|
122
146
|
collection.stub(:collection => [ user, user ])
|
123
147
|
end
|
124
148
|
|
125
|
-
it
|
149
|
+
it 'should return a collection of objects' do
|
126
150
|
User.collection.should == [ user, user ]
|
127
151
|
end
|
128
152
|
end
|
129
153
|
|
130
|
-
describe
|
154
|
+
describe '#errors=' do
|
131
155
|
before :each do
|
132
|
-
@user = User.new(:errors => {
|
156
|
+
@user = User.new(:errors => { 'a' => 'message', 'b' => 'message' })
|
133
157
|
end
|
134
158
|
|
135
|
-
it
|
159
|
+
it 'should set @errors with symbolic keys and messages as an array' do
|
136
160
|
@user.errors.messages.should == { :a => %w(message), :b => %w(message) }
|
137
161
|
end
|
138
162
|
end
|
139
163
|
|
140
|
-
describe
|
141
|
-
context
|
164
|
+
describe 'requests' do
|
165
|
+
context 'on the class' do
|
142
166
|
before :each do
|
143
|
-
stub_request(:any,
|
167
|
+
stub_request(:any, 'http://api.example.com/users').to_return(:body => {'a' => 'b'}.to_json)
|
144
168
|
end
|
145
169
|
|
146
|
-
it
|
170
|
+
it 'should return a new instance' do
|
147
171
|
User.get.should be_an_instance_of(User)
|
148
172
|
end
|
149
173
|
|
150
|
-
it
|
151
|
-
User.get.response.should == {
|
174
|
+
it 'should set the response on the instance' do
|
175
|
+
User.get.response.should == { 'a' => 'b' }
|
152
176
|
end
|
153
177
|
end
|
154
178
|
|
155
|
-
context
|
179
|
+
context 'on an object' do
|
156
180
|
before :each do
|
157
|
-
stub_request(:any,
|
181
|
+
stub_request(:any, 'http://api.example.com/users').to_return(:body => {'a' => 'b'}.to_json)
|
158
182
|
@user = User.new
|
159
183
|
end
|
160
184
|
|
161
|
-
it
|
185
|
+
it 'should return a new instance' do
|
162
186
|
@user.get.should be_an_instance_of(User)
|
163
187
|
end
|
164
188
|
|
165
|
-
it
|
166
|
-
@user.get.response.should == {
|
189
|
+
it 'should set the response on the instance' do
|
190
|
+
@user.get.response.should == {'a' => 'b'}
|
167
191
|
end
|
168
192
|
end
|
169
193
|
end
|
170
|
-
end
|
194
|
+
end
|
@@ -4,17 +4,17 @@ describe ApiClient::Collection do
|
|
4
4
|
let(:user) { User.new }
|
5
5
|
|
6
6
|
before :each do
|
7
|
-
stub_request(:get,
|
7
|
+
stub_request(:get, 'http://api.example.com/users').to_return(:body => [ { 'a' => 'b' }, { 'a' => 'b2' } ].to_json)
|
8
8
|
User.stub(:new => user)
|
9
|
-
@collection = ApiClient::Collection.new(User,
|
9
|
+
@collection = ApiClient::Collection.new(User, 'users')
|
10
10
|
end
|
11
11
|
|
12
|
-
it
|
12
|
+
it 'should include enumerable module' do
|
13
13
|
@collection.should respond_to(:first)
|
14
14
|
end
|
15
15
|
|
16
|
-
describe
|
17
|
-
it
|
16
|
+
describe '.initialize' do
|
17
|
+
it 'Should initialize a collection of Objects' do
|
18
18
|
@collection.collection.should == [user, user]
|
19
19
|
end
|
20
20
|
end
|
@@ -1,51 +1,51 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
|
3
3
|
describe ApiClient::Configuration do
|
4
|
-
describe
|
5
|
-
describe
|
4
|
+
describe '#path' do
|
5
|
+
describe 'when not configured' do
|
6
6
|
before :each do
|
7
7
|
ApiClient.configure do |config|
|
8
|
-
config.path =
|
8
|
+
config.path = ''
|
9
9
|
end
|
10
10
|
end
|
11
11
|
|
12
|
-
it
|
12
|
+
it 'should raise an error' do
|
13
13
|
lambda { ApiClient.config.path }.should raise_error(ApiClient::Exceptions::NotConfigured)
|
14
14
|
end
|
15
15
|
end
|
16
16
|
|
17
|
-
describe
|
17
|
+
describe 'when properly configured' do
|
18
18
|
before :each do
|
19
19
|
ApiClient.configure do |config|
|
20
|
-
config.path =
|
20
|
+
config.path = 'http://api.example.com'
|
21
21
|
end
|
22
22
|
end
|
23
23
|
|
24
|
-
it
|
24
|
+
it 'should return the path value' do
|
25
25
|
ApiClient.config.path.should_not be_nil
|
26
26
|
end
|
27
27
|
end
|
28
28
|
end
|
29
29
|
|
30
|
-
describe
|
30
|
+
describe '#path=' do
|
31
31
|
describe "with a string without '/'" do
|
32
32
|
before :each do
|
33
|
-
ApiClient.config.path =
|
33
|
+
ApiClient.config.path = 'http://api.example.com'
|
34
34
|
end
|
35
35
|
|
36
36
|
it "should set it with a '/'" do
|
37
|
-
ApiClient.config.path.should ==
|
37
|
+
ApiClient.config.path.should == 'http://api.example.com/'
|
38
38
|
end
|
39
39
|
end
|
40
40
|
|
41
41
|
describe "with a string with '/'" do
|
42
42
|
before :each do
|
43
|
-
ApiClient.config.path =
|
43
|
+
ApiClient.config.path = 'http://api.example.com/'
|
44
44
|
end
|
45
45
|
|
46
46
|
it "should set it as passed" do
|
47
|
-
ApiClient.config.path.should ==
|
47
|
+
ApiClient.config.path.should == 'http://api.example.com/'
|
48
48
|
end
|
49
49
|
end
|
50
50
|
end
|
51
|
-
end
|
51
|
+
end
|
@@ -2,36 +2,36 @@ require 'spec_helper'
|
|
2
2
|
|
3
3
|
describe ApiClient::Dispatcher do
|
4
4
|
before :each do
|
5
|
-
stub_request(:any,
|
5
|
+
stub_request(:any, 'http://api.example.com/user/5').to_return(:body => 'asd')
|
6
6
|
end
|
7
7
|
|
8
|
-
describe
|
9
|
-
it
|
10
|
-
ApiClient::Dispatcher.get(
|
8
|
+
describe '.get' do
|
9
|
+
it 'should return the request' do
|
10
|
+
ApiClient::Dispatcher.get('http://api.example.com/user/5', {}).body.should == ('asd')
|
11
11
|
end
|
12
12
|
end
|
13
13
|
|
14
|
-
describe
|
15
|
-
it
|
16
|
-
ApiClient::Dispatcher.post(
|
14
|
+
describe '.post' do
|
15
|
+
it 'should return the request' do
|
16
|
+
ApiClient::Dispatcher.post('http://api.example.com/user/5', {}, {}).body.should == ('asd')
|
17
17
|
end
|
18
18
|
end
|
19
19
|
|
20
|
-
describe
|
21
|
-
it
|
22
|
-
ApiClient::Dispatcher.put(
|
20
|
+
describe '.put' do
|
21
|
+
it 'should return the request' do
|
22
|
+
ApiClient::Dispatcher.put('http://api.example.com/user/5', {}, {}).body.should == ('asd')
|
23
23
|
end
|
24
24
|
end
|
25
25
|
|
26
|
-
describe
|
27
|
-
it
|
28
|
-
ApiClient::Dispatcher.patch(
|
26
|
+
describe '.patch' do
|
27
|
+
it 'should return the request' do
|
28
|
+
ApiClient::Dispatcher.patch('http://api.example.com/user/5', {}, {}).body.should == ('asd')
|
29
29
|
end
|
30
30
|
end if ApiClient::Dispatcher.respond_to?(:patch)
|
31
31
|
|
32
|
-
describe
|
33
|
-
it
|
34
|
-
ApiClient::Dispatcher.delete(
|
32
|
+
describe '.delete' do
|
33
|
+
it 'should return the request' do
|
34
|
+
ApiClient::Dispatcher.delete('http://api.example.com/user/5', {}).body.should == ('asd')
|
35
35
|
end
|
36
36
|
end
|
37
37
|
end
|
@@ -1,35 +1,35 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
|
3
3
|
describe ApiClient::Errors do
|
4
|
-
describe
|
4
|
+
describe '#add_errors' do
|
5
5
|
before :each do
|
6
|
-
@errors = ApiClient::Errors.new(self).add_errors({:a => 'b'})
|
6
|
+
@errors = ApiClient::Errors.new(self).add_errors({ :a => 'b' })
|
7
7
|
end
|
8
8
|
|
9
|
-
it
|
9
|
+
it 'should initialize a new object' do
|
10
10
|
@errors[:a].should == 'b'
|
11
11
|
end
|
12
12
|
end
|
13
13
|
|
14
|
-
describe
|
14
|
+
describe '#unique_messages' do
|
15
15
|
before :each do
|
16
16
|
@user = User.new
|
17
17
|
@user.valid?
|
18
18
|
end
|
19
19
|
|
20
|
-
it
|
20
|
+
it 'should set a unique message for each attribute' do
|
21
21
|
@user.errors.unique_messages.should == { :a => "can't be blank and is not included in the list" }
|
22
22
|
end
|
23
23
|
end
|
24
24
|
|
25
|
-
describe
|
25
|
+
describe '#unique_message' do
|
26
26
|
before :each do
|
27
27
|
@user = User.new
|
28
28
|
@user.valid?
|
29
29
|
end
|
30
30
|
|
31
|
-
it
|
31
|
+
it 'should return a unique message for the given attribute' do
|
32
32
|
@user.errors.unique_message(:a).should == "can't be blank and is not included in the list"
|
33
33
|
end
|
34
34
|
end
|
35
|
-
end
|
35
|
+
end
|
@@ -1,95 +1,95 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
|
3
3
|
describe ApiClient::Parser do
|
4
|
-
describe
|
5
|
-
context
|
4
|
+
describe '#response' do
|
5
|
+
context 'with a valid json response' do
|
6
6
|
before :each do
|
7
|
-
stub_request(:post,
|
7
|
+
stub_request(:post, 'http://api.example.com/user/5').to_return(:body => {:base => { :a => :b } }.to_json, :status => '201')
|
8
8
|
@response = ApiClient::Dispatcher.post('http://api.example.com/user/5', {}, {})
|
9
9
|
end
|
10
10
|
|
11
|
-
it
|
12
|
-
ApiClient::Parser.response(@response, 'http://api.example.com/user/5').should == {
|
11
|
+
it 'should return the response code and the body parsed' do
|
12
|
+
ApiClient::Parser.response(@response, 'http://api.example.com/user/5').should == { 'base' => { 'a' => 'b' } }
|
13
13
|
end
|
14
14
|
end
|
15
15
|
|
16
|
-
context
|
16
|
+
context 'with a invalid json response' do
|
17
17
|
before :each do
|
18
|
-
stub_request(:post,
|
18
|
+
stub_request(:post, 'http://api.example.com/user/5').to_return(:body => 'wrong', :status => '201')
|
19
19
|
@response = ApiClient::Dispatcher.post('http://api.example.com/user/5', {}, {})
|
20
20
|
end
|
21
21
|
|
22
|
-
it
|
22
|
+
it 'should return the response code and an empty hash' do
|
23
23
|
ApiClient::Parser.response(@response, 'http://api.example.com/user/5').should == {}
|
24
24
|
end
|
25
25
|
end
|
26
26
|
|
27
|
-
context
|
28
|
-
context
|
27
|
+
context 'with a response code of' do
|
28
|
+
context '401' do
|
29
29
|
before :each do
|
30
|
-
stub_request(:get,
|
30
|
+
stub_request(:get, 'http://api.example.com/user/5').to_return(:status => 401)
|
31
31
|
@response = ApiClient::Dispatcher.get('http://api.example.com/user/5')
|
32
32
|
end
|
33
33
|
|
34
|
-
it
|
34
|
+
it 'should raise a Unauthorized exception' do
|
35
35
|
lambda { ApiClient::Parser.response(@response, 'http://api.example.com/user/5') }.should raise_error(ApiClient::Exceptions::Unauthorized)
|
36
36
|
end
|
37
37
|
end
|
38
38
|
|
39
|
-
context
|
39
|
+
context '403' do
|
40
40
|
before :each do
|
41
|
-
stub_request(:get,
|
41
|
+
stub_request(:get, 'http://api.example.com/user/5').to_return(:status => 403)
|
42
42
|
@response = ApiClient::Dispatcher.get('http://api.example.com/user/5')
|
43
43
|
end
|
44
44
|
|
45
|
-
it
|
45
|
+
it 'should raise a Forbidden exception' do
|
46
46
|
lambda { ApiClient::Parser.response(@response, 'http://api.example.com/user/5') }.should raise_error(ApiClient::Exceptions::Forbidden)
|
47
47
|
end
|
48
48
|
end
|
49
49
|
|
50
|
-
context
|
50
|
+
context '404' do
|
51
51
|
before :each do
|
52
|
-
stub_request(:get,
|
52
|
+
stub_request(:get, 'http://api.example.com/user/5').to_return(:status => 404)
|
53
53
|
@response = ApiClient::Dispatcher.get('http://api.example.com/user/5')
|
54
54
|
end
|
55
55
|
|
56
|
-
it
|
56
|
+
it 'should raise a NotFound exception' do
|
57
57
|
lambda { ApiClient::Parser.response(@response, 'http://api.example.com/user/5') }.should raise_error(ApiClient::Exceptions::NotFound, "http://api.example.com/user/5")
|
58
58
|
end
|
59
59
|
end
|
60
60
|
|
61
|
-
context
|
61
|
+
context '500' do
|
62
62
|
before :each do
|
63
|
-
stub_request(:get,
|
63
|
+
stub_request(:get, 'http://api.example.com/user/5').to_return(:status => 500)
|
64
64
|
@response = ApiClient::Dispatcher.get('http://api.example.com/user/5')
|
65
65
|
end
|
66
66
|
|
67
|
-
it
|
67
|
+
it 'should raise a InternalServerError exception' do
|
68
68
|
lambda { ApiClient::Parser.response(@response, 'http://api.example.com/user/5') }.should raise_error(ApiClient::Exceptions::InternalServerError)
|
69
69
|
end
|
70
70
|
end
|
71
71
|
|
72
|
-
context
|
72
|
+
context '502' do
|
73
73
|
before :each do
|
74
|
-
stub_request(:get,
|
74
|
+
stub_request(:get, 'http://api.example.com/user/5').to_return(:status => 502)
|
75
75
|
@response = ApiClient::Dispatcher.get('http://api.example.com/user/5')
|
76
76
|
end
|
77
77
|
|
78
|
-
it
|
78
|
+
it 'should raise a BadGateway exception' do
|
79
79
|
lambda { ApiClient::Parser.response(@response, 'http://api.example.com/user/5') }.should raise_error(ApiClient::Exceptions::BadGateway)
|
80
80
|
end
|
81
81
|
end
|
82
82
|
|
83
83
|
context "503" do
|
84
84
|
before :each do
|
85
|
-
stub_request(:get,
|
85
|
+
stub_request(:get, 'http://api.example.com/user/5').to_return(:status => 503)
|
86
86
|
@response = ApiClient::Dispatcher.get('http://api.example.com/user/5')
|
87
87
|
end
|
88
88
|
|
89
|
-
it
|
89
|
+
it 'should raise a ServiceUnavailable exception' do
|
90
90
|
lambda { ApiClient::Parser.response(@response, 'http://api.example.com/user/5') }.should raise_error(ApiClient::Exceptions::ServiceUnavailable)
|
91
91
|
end
|
92
92
|
end
|
93
93
|
end
|
94
94
|
end
|
95
|
-
end
|
95
|
+
end
|
data/spec/spec_helper.rb
CHANGED
@@ -1,11 +1,11 @@
|
|
1
|
-
require
|
2
|
-
require
|
3
|
-
require
|
4
|
-
require
|
1
|
+
require 'rspec'
|
2
|
+
require 'webmock/rspec'
|
3
|
+
require 'json'
|
4
|
+
require 'coveralls'
|
5
5
|
|
6
6
|
Coveralls.wear!
|
7
7
|
|
8
|
-
require File.dirname(__FILE__)
|
8
|
+
require "#{File.dirname(__FILE__)}/../lib/api-client"
|
9
9
|
|
10
10
|
class User < ApiClient::Base
|
11
11
|
attr_accessor :a, :b
|
@@ -15,19 +15,19 @@ class User < ApiClient::Base
|
|
15
15
|
end
|
16
16
|
|
17
17
|
class Admin < ApiClient::Base
|
18
|
-
self.remote_object =
|
18
|
+
self.remote_object = 'user'
|
19
19
|
|
20
20
|
attr_accessor :a, :b
|
21
21
|
end
|
22
22
|
|
23
23
|
class Post < ApiClient::Base
|
24
|
-
self.association = { :writer =>
|
24
|
+
self.association = { :writer => 'User' }
|
25
25
|
|
26
26
|
attr_accessor :a
|
27
27
|
end
|
28
28
|
|
29
29
|
class Group < ApiClient::Base
|
30
|
-
self.associations = { :members =>
|
30
|
+
self.associations = { :members => 'User', :owner => 'Admin' }
|
31
31
|
end
|
32
32
|
|
33
33
|
ApiClient.configure do |config|
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: api-client
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.0.0.
|
4
|
+
version: 2.0.0.rc2
|
5
5
|
prerelease: 6
|
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-06-
|
12
|
+
date: 2013-06-09 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: rake
|
@@ -192,7 +192,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
192
192
|
version: '0'
|
193
193
|
segments:
|
194
194
|
- 0
|
195
|
-
hash:
|
195
|
+
hash: -2780574729308827888
|
196
196
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
197
197
|
none: false
|
198
198
|
requirements:
|
@@ -205,5 +205,20 @@ rubygems_version: 1.8.25
|
|
205
205
|
signing_key:
|
206
206
|
specification_version: 3
|
207
207
|
summary: Client to make Api calls
|
208
|
-
test_files:
|
208
|
+
test_files:
|
209
|
+
- examples/config/initializers/api-client.rb
|
210
|
+
- examples/controllers/application_controller.rb
|
211
|
+
- examples/controllers/user_controller.rb
|
212
|
+
- examples/models/admin.rb
|
213
|
+
- examples/models/group.rb
|
214
|
+
- examples/models/user.rb
|
215
|
+
- gemfiles/Gemfile.net_http
|
216
|
+
- gemfiles/Gemfile.typhoeus
|
217
|
+
- spec/api-client/base_spec.rb
|
218
|
+
- spec/api-client/collection_spec.rb
|
219
|
+
- spec/api-client/configuration_spec.rb
|
220
|
+
- spec/api-client/dispatcher_spec.rb
|
221
|
+
- spec/api-client/errors_spec.rb
|
222
|
+
- spec/api-client/parser_spec.rb
|
223
|
+
- spec/spec_helper.rb
|
209
224
|
has_rdoc:
|