api-client 1.10.0 → 2.0.0.rc1

Sign up to get free protection for your applications and to get access to all the features.
data/CHANGELOG.md CHANGED
@@ -1,5 +1,9 @@
1
1
  # CHANGELOG
2
2
 
3
+ ## v1.10.0
4
+
5
+ * Add Support for api responses with collections
6
+
3
7
  ## v1.9.1
4
8
 
5
9
  * Fix for Net::Http on NotFound Exception
data/README.md CHANGED
@@ -66,7 +66,15 @@ class User < ApiClient::Base
66
66
  Then, on your action, just put into it:
67
67
 
68
68
  ```ruby
69
- @user = User.get("http://api.example.com/user/3")
69
+ @user = User.get(3)
70
+ ```
71
+
72
+ where 3 is the id of the user.
73
+
74
+ To a request that returns a collection of the object, use:
75
+
76
+ ```ruby
77
+ @user = User.collection
70
78
  ```
71
79
 
72
80
  ## Advanced Usage
@@ -104,4 +112,4 @@ This code will create a setter and a getter for houses and cars and initialize t
104
112
  2. Create your feature branch (`git checkout -b my-new-feature`)
105
113
  3. Commit your changes (`git commit -am 'Added some feature'`)
106
114
  4. Push to the branch (`git push origin my-new-feature`)
107
- 5. Create new Pull Request
115
+ 5. Create new Pull Request
data/api-client.gemspec CHANGED
@@ -9,7 +9,7 @@ Gem::Specification.new do |gem|
9
9
  gem.summary = %q{Client to make Api calls}
10
10
 
11
11
  gem.files = `git ls-files`.split("\n")
12
- gem.test_files = `git ls-files -- {test,spec,features, gemfiles}/*`.split("\n")
12
+ gem.test_files = `git ls-files -- {test,spec,features,examples,gemfiles}/*`.split("\n")
13
13
  gem.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
14
14
  gem.require_paths = %w(lib)
15
15
 
@@ -0,0 +1,5 @@
1
+ # Global Configuration
2
+ # Api path
3
+ ApiClient.configure do |config|
4
+ config.path = "http://api.example.com"
5
+ end
@@ -1,38 +1,45 @@
1
+ # It will works with respond_with.
2
+ # Your action should looks like any other one: A model with a method call. =D
1
3
  class UserController < ApplicationController
2
- # It will works with respond_with.
3
- # Your action should looks like any other one: A model with a method call. =D
4
+ # It will hit http://api.example.com/users with a get request
4
5
  def index
5
- @users = User.get("api.example.com/users")
6
+ @users = User.collection
6
7
  respond_with(@users)
7
8
  end
8
9
 
10
+ # It will initialize a new object based on the attribute accessors
9
11
  def new
10
12
  @user = User.new
11
13
  respond_with(@user)
12
14
  end
13
15
 
16
+ # It will hit http://api.example.com/users with a post request
14
17
  def create
15
- @user = User.post("api.example.com/users", :user => params[:user])
18
+ @user = User.post("", :user => params[:user])
16
19
  respond_with(@user)
17
20
  end
18
21
 
22
+ # It will hit http://api.example.com/users/1 with a get request
19
23
  def edit
20
- @user = User.get("api.example.com/users/#{params[:id]}")
24
+ @user = User.get(params[:id])
21
25
  respond_with(@user)
22
26
  end
23
27
 
28
+ # It will hit http://api.example.com/users/1 with a patch request
24
29
  def update
25
- @user = User.patch("api.example.com/users", { :id => params[:id], :user => params[:user]})
30
+ @user = User.patch("", { :id => params[:id], :user => params[:user] })
26
31
  respond_with(@user)
27
32
  end
28
33
 
34
+ # It will hit http://api.example.com/users/1 with a get request
29
35
  def show
30
- @user = User.get("api.example.com/users/#{params[:id]}")
36
+ @user = User.get(params[:id])
31
37
  respond_with(@user)
32
38
  end
33
39
 
40
+ # It will hit http://api.example.com/users/1 with a delete request
34
41
  def delete
35
- @user = User.delete("api.example.com/users/#{params[:id]}")
42
+ @user = User.delete(params[:id])
36
43
  respond_with(@user)
37
44
  end
38
- end
45
+ end
@@ -8,4 +8,4 @@ class Admin < ApiClient::Base
8
8
  # Validations will work as well
9
9
  validates :email, :presence => true, :uniqueness => true
10
10
  validates :password, :confirmation => true
11
- end
11
+ end
@@ -1,3 +1,3 @@
1
1
  class Group < ApiClient::Base
2
2
  self.associations = { :members => "User", :owner => "Admin" }
3
- end
3
+ end
@@ -7,4 +7,4 @@ class User < ApiClient::Base
7
7
  # Validations will work as well
8
8
  validates :email, :presence => true, :uniqueness => true
9
9
  validates :password, :confirmation => true
10
- end
10
+ end
data/lib/api-client.rb CHANGED
@@ -7,9 +7,10 @@ module ApiClient
7
7
  autoload :Configuration, 'api-client/configuration'
8
8
  autoload :Base, 'api-client/base'
9
9
  autoload :Collection, 'api-client/collection'
10
+ autoload :ClassMethods, 'api-client/class_methods'
11
+ autoload :InstanceMethods, 'api-client/instance_methods'
10
12
  autoload :Dispatcher, 'api-client/dispatcher'
11
13
  autoload :Parser, 'api-client/parser'
12
- autoload :Builder, 'api-client/builder'
13
14
 
14
15
  # Configures global settings
15
16
  # ApiClient.configure do |config|
@@ -27,4 +28,4 @@ module ApiClient
27
28
  configure do |config|
28
29
  config.path = ''
29
30
  end
30
- end
31
+ end
@@ -12,7 +12,8 @@ module ApiClient
12
12
  include ActiveModel::Conversion
13
13
  extend ActiveModel::Naming
14
14
 
15
- extend ApiClient::Builder
15
+ extend ApiClient::ClassMethods
16
+ include ApiClient::InstanceMethods
16
17
 
17
18
  # @return [Hash] the request response.
18
19
  attr_accessor :response
@@ -71,7 +72,7 @@ module ApiClient
71
72
  # Set methods to initialize associated objects.
72
73
  #
73
74
  # @param [Hash] association classes.
74
- def self.associations(associations = {})
75
+ def self.associations=(associations = {})
75
76
  associations.each do |association, class_name|
76
77
  class_eval <<-EVAL
77
78
  def #{association.to_s}=(attributes = {})
@@ -86,7 +87,7 @@ module ApiClient
86
87
  end
87
88
 
88
89
  class << self
89
- alias_method :association, :associations
90
+ alias_method :association=, :associations=
90
91
  end
91
92
 
92
93
  # Overwrite #attr_acessor method to save instance_variable names.
@@ -94,7 +95,7 @@ module ApiClient
94
95
  # @param [Array] instance variables.
95
96
  def self.attr_accessor(*vars)
96
97
  @attributes ||= []
97
- @attributes.concat vars
98
+ @attributes.concat(vars)
98
99
  super
99
100
  end
100
101
 
@@ -119,8 +120,8 @@ module ApiClient
119
120
  #
120
121
  # @param [String] url to get the collection.
121
122
  # @return [Collection] a collection of objects.
122
- def self.collection(url)
123
- ApiClient::Collection.new(self, url).collection
123
+ def self.collection
124
+ ApiClient::Collection.new(self, self.path).collection
124
125
  end
125
126
 
126
127
  # Set the hash of errors, making keys symbolic.
@@ -129,12 +130,5 @@ module ApiClient
129
130
  def errors=(errs = {})
130
131
  errors.add_errors(Hash[errs.map{|(key,value)| [key.to_sym,value]}])
131
132
  end
132
-
133
- protected
134
-
135
- def self.method_missing(method, *args)
136
- @response = ApiClient::Parser.response(ApiClient::Dispatcher.send(method, *args), *args[0])
137
- build(self, @response)
138
- end
139
133
  end
140
- end
134
+ end
@@ -0,0 +1,30 @@
1
+ module ApiClient
2
+ # This module handles the logic to make an api call and initialize an object with the response.
3
+ module ClassMethods
4
+ # Initialize an object based on a hash of attributes.
5
+ #
6
+ # @param [Hash] attributes hash of attributes.
7
+ # @return [Base] the object initialized.
8
+ def build(params)
9
+ if params.key?(remote_object)
10
+ new(params[remote_object].merge(:response => params))
11
+ else
12
+ new(params.merge(:response => params))
13
+ end
14
+ end
15
+
16
+ # Make the api call and pass the parsed response to build to create a new object.
17
+ #
18
+ # @param [Symbol] method_name the name of the method.
19
+ # @param [Integer] id the id of the object.
20
+ # @param [Array] args an array of params.
21
+ # @return [Base] the object initialized.
22
+ def method_missing(method_name, id = nil, *args)
23
+ url = "#{ApiClient.config.path}#{self.path}"
24
+ "#{url}/#{id}" unless id.nil?
25
+ response = ApiClient::Dispatcher.send(method_name.to_sym, url, *args)
26
+ params = ApiClient::Parser.response(response, url)
27
+ build(params)
28
+ end
29
+ end
30
+ end
@@ -9,7 +9,8 @@ class ApiClient::Collection
9
9
  # @param [Class] The class to instantiate the objects.
10
10
  # @param [String] The url to get the data.
11
11
  # @return [Collection] the collection of objects.
12
- def initialize(klass, url)
12
+ def initialize(klass, resource_path)
13
+ url = "#{ApiClient.config.path}#{resource_path}"
13
14
  @collection = ApiClient::Parser.response(ApiClient::Dispatcher.get(url), url)
14
15
  @collection.map! do |attributes|
15
16
  klass.new(attributes)
@@ -0,0 +1,37 @@
1
+ module ApiClient
2
+ # This module handles the logic to make an api call and update the current object with the response.
3
+ module InstanceMethods
4
+ # Update an object based on a hash of attributes.
5
+ #
6
+ # @param [Hash] attributes hash of attributes.
7
+ # @return [Base] the updated object.
8
+ def update(params)
9
+ if params.key?(self.class.remote_object)
10
+ params[self.class.remote_object].each do |key, value|
11
+ instance_variable_set(key.to_sym, value)
12
+ end
13
+ instance_variable_set(response.to_sym, params[self.class.remote_object])
14
+ else
15
+ params.each do |key, value|
16
+ instance_variable_set("@#{key}", value)
17
+ end
18
+ instance_variable_set("@response", params)
19
+ end
20
+ self
21
+ end
22
+
23
+ # Make the api call and pass the parsed response to update the current object.
24
+ #
25
+ # @param [Symbol] method_name the name of the method.
26
+ # @param [Integer] id the id of the current object.
27
+ # @param [Array] args an array of params.
28
+ # @return [Base] the object updated.
29
+ def method_missing(method_name, id = nil, *args)
30
+ url = "#{ApiClient.config.path}#{self.class.path}"
31
+ "#{url}/#{id}" unless id.nil?
32
+ response = ApiClient::Dispatcher.send(method_name.to_sym, url, *args)
33
+ params = ApiClient::Parser.response(response, url)
34
+ update(params)
35
+ end
36
+ end
37
+ end
@@ -1,5 +1,5 @@
1
1
  # High Level Namespace of the library ApiClient.
2
2
  module ApiClient
3
3
  # Version of the library.
4
- VERSION = "1.10.0"
4
+ VERSION = "2.0.0.rc1"
5
5
  end
@@ -118,12 +118,12 @@ describe ApiClient::Base do
118
118
 
119
119
  describe "#collection" do
120
120
  before :each do
121
- ApiClient::Collection.stub(:new).with(User, "http://api.example.com").and_return(collection)
121
+ ApiClient::Collection.stub(:new).with(User, "users").and_return(collection)
122
122
  collection.stub(:collection => [ user, user ])
123
123
  end
124
124
 
125
125
  it "should return a collection of objects" do
126
- User.collection("http://api.example.com").should == [ user, user ]
126
+ User.collection.should == [ user, user ]
127
127
  end
128
128
  end
129
129
 
@@ -138,28 +138,33 @@ describe ApiClient::Base do
138
138
  end
139
139
 
140
140
  describe "requests" do
141
- context "with an object as response" do
141
+ context "on the class" do
142
142
  before :each do
143
- stub_request(:any, "http://api.example.com").to_return(:body => {"a" => "b"}.to_json)
143
+ stub_request(:any, "http://api.example.com/users").to_return(:body => {"a" => "b"}.to_json)
144
144
  end
145
145
 
146
146
  it "should return a new instance" do
147
- User.get("http://api.example.com").should be_an_instance_of(User)
147
+ User.get.should be_an_instance_of(User)
148
148
  end
149
149
 
150
150
  it "should set the response on the instance" do
151
- User.get("http://api.example.com").response.should == {"a" => "b"}
151
+ User.get.response.should == {"a" => "b"}
152
152
  end
153
153
  end
154
154
 
155
- context "with an array as response" do
155
+ context "on an object" do
156
156
  before :each do
157
- stub_request(:any, "http://api.example.com").to_return(:body => [{"a" => "b"}].to_json)
157
+ stub_request(:any, "http://api.example.com/users").to_return(:body => {"a" => "b"}.to_json)
158
+ @user = User.new
158
159
  end
159
160
 
160
- it "should return an array of instances" do
161
- User.get("http://api.example.com").should be_an_instance_of(Array)
161
+ it "should return a new instance" do
162
+ @user.get.should be_an_instance_of(User)
163
+ end
164
+
165
+ it "should set the response on the instance" do
166
+ @user.get.response.should == {"a" => "b"}
162
167
  end
163
168
  end
164
169
  end
165
- end
170
+ end
@@ -4,9 +4,9 @@ describe ApiClient::Collection do
4
4
  let(:user) { User.new }
5
5
 
6
6
  before :each do
7
- stub_request(:get, "http://api.example.com").to_return(:body => [ {"a" => "b"}, {"a" => "b2"} ].to_json)
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, "http://api.example.com")
9
+ @collection = ApiClient::Collection.new(User, "users")
10
10
  end
11
11
 
12
12
  it "should include enumerable module" do
@@ -3,6 +3,12 @@ require 'spec_helper'
3
3
  describe ApiClient::Configuration do
4
4
  describe "#path" do
5
5
  describe "when not configured" do
6
+ before :each do
7
+ ApiClient.configure do |config|
8
+ config.path = ""
9
+ end
10
+ end
11
+
6
12
  it "should raise an error" do
7
13
  lambda { ApiClient.config.path }.should raise_error(ApiClient::Exceptions::NotConfigured)
8
14
  end
@@ -11,7 +17,7 @@ describe ApiClient::Configuration do
11
17
  describe "when properly configured" do
12
18
  before :each do
13
19
  ApiClient.configure do |config|
14
- config.path = "api.example.com"
20
+ config.path = "http://api.example.com"
15
21
  end
16
22
  end
17
23
 
@@ -24,21 +30,21 @@ describe ApiClient::Configuration do
24
30
  describe "#path=" do
25
31
  describe "with a string without '/'" do
26
32
  before :each do
27
- ApiClient.config.path = "api.example.com"
33
+ ApiClient.config.path = "http://api.example.com"
28
34
  end
29
35
 
30
36
  it "should set it with a '/'" do
31
- ApiClient.config.path.should == "api.example.com/"
37
+ ApiClient.config.path.should == "http://api.example.com/"
32
38
  end
33
39
  end
34
40
 
35
41
  describe "with a string with '/'" do
36
42
  before :each do
37
- ApiClient.config.path = "api.example.com/"
43
+ ApiClient.config.path = "http://api.example.com/"
38
44
  end
39
45
 
40
46
  it "should set it as passed" do
41
- ApiClient.config.path.should == "api.example.com/"
47
+ ApiClient.config.path.should == "http://api.example.com/"
42
48
  end
43
49
  end
44
50
  end
data/spec/spec_helper.rb CHANGED
@@ -21,11 +21,15 @@ class Admin < ApiClient::Base
21
21
  end
22
22
 
23
23
  class Post < ApiClient::Base
24
- self.association({ :writer => "User" })
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 => "User", :owner => "Admin" })
30
+ self.associations = { :members => "User", :owner => "Admin" }
31
31
  end
32
+
33
+ ApiClient.configure do |config|
34
+ config.path = 'http://api.example.com'
35
+ end
metadata CHANGED
@@ -1,15 +1,15 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: api-client
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.10.0
5
- prerelease:
4
+ version: 2.0.0.rc1
5
+ prerelease: 6
6
6
  platform: ruby
7
7
  authors:
8
8
  - Paulo Henrique Lopes Ribeiro
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2013-06-04 00:00:00.000000000 Z
12
+ date: 2013-06-05 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: rake
@@ -140,6 +140,7 @@ files:
140
140
  - README.md
141
141
  - Rakefile
142
142
  - api-client.gemspec
143
+ - examples/config/initializers/api-client.rb
143
144
  - examples/controllers/application_controller.rb
144
145
  - examples/controllers/user_controller.rb
145
146
  - examples/models/admin.rb
@@ -149,7 +150,7 @@ files:
149
150
  - gemfiles/Gemfile.typhoeus
150
151
  - lib/api-client.rb
151
152
  - lib/api-client/base.rb
152
- - lib/api-client/builder.rb
153
+ - lib/api-client/class_methods.rb
153
154
  - lib/api-client/collection.rb
154
155
  - lib/api-client/configuration.rb
155
156
  - lib/api-client/dispatcher.rb
@@ -166,6 +167,7 @@ files:
166
167
  - lib/api-client/exceptions/not_found.rb
167
168
  - lib/api-client/exceptions/service_unavailable.rb
168
169
  - lib/api-client/exceptions/unauthorized.rb
170
+ - lib/api-client/instance_methods.rb
169
171
  - lib/api-client/net/http.rb
170
172
  - lib/api-client/parser.rb
171
173
  - lib/api-client/version.rb
@@ -190,16 +192,13 @@ required_ruby_version: !ruby/object:Gem::Requirement
190
192
  version: '0'
191
193
  segments:
192
194
  - 0
193
- hash: 4163480247094767209
195
+ hash: 3711980256019663374
194
196
  required_rubygems_version: !ruby/object:Gem::Requirement
195
197
  none: false
196
198
  requirements:
197
- - - ! '>='
199
+ - - ! '>'
198
200
  - !ruby/object:Gem::Version
199
- version: '0'
200
- segments:
201
- - 0
202
- hash: 4163480247094767209
201
+ version: 1.3.1
203
202
  requirements: []
204
203
  rubyforge_project:
205
204
  rubygems_version: 1.8.25
@@ -1,12 +0,0 @@
1
- module ApiClient
2
- module Builder
3
- def build(object, params)
4
- case true
5
- when params.instance_of?(Array) then return params.map { |a| new(a.merge(:response => params)) }
6
- when params.key?(remote_object) then return new(params[remote_object].merge(:response => params))
7
- when params.key?(remote_object.pluralize) then return params[remote_object.pluralize].map { |a| new(a.merge(:response => params)) }
8
- else return new(params.merge(:response => params))
9
- end
10
- end
11
- end
12
- end