api-client 2.0.0.rc1 → 2.0.0.rc2
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 +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:
|