jeckle 0.2.1 → 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: cc145a2c57d49e16a1eb949572d0e5d5b332e84c
4
- data.tar.gz: d9777c608e3647a7a4280c9d2b6a9c7accb0156e
3
+ metadata.gz: 0fedf58b9859236e613f70bb3cfaf8f34fcba6cd
4
+ data.tar.gz: f5671e5ec06652de45455208795669c487decaa8
5
5
  SHA512:
6
- metadata.gz: 0ce7714c1ba50c9feafa7327766f9eb8d8e5d515c02e9928519eeb6f9b8f7f60e272d68bc0b7ef6080a31218c1a3b4f94f647fa04b7d4c53d8d270c1160dc4c7
7
- data.tar.gz: d5aa1c13218e74e196d08b9236e2f2b5c35a232aca955c8d0aabcba610adc823722f33fc240b8f1b4dc5fabc42989f2ff23d79ac66b9c2989a15904c8d959824
6
+ metadata.gz: d052c4ef86214fcd06f9f84c9f959e02c5c83c2d3560652f8d0fb5206f3a090f8b09d8662cd500bb125206f20cd3d7f44d2dcf33a464bfdbac66b7f99ef6d0a1
7
+ data.tar.gz: 58f383cc88ac992dbef23a98e2c5af620d0c14fdf774373f8a8aa9f07a0b0f722ee496caa03769fd4324c6e7b3e060c0f65bb12f0e424e8ddb56b18da4a86ffc
data/History.markdown ADDED
@@ -0,0 +1,11 @@
1
+ ## v.0.3.0
2
+
3
+ * Change Jeckle::Resource.default_api to Jeckle::Resource.api
4
+
5
+ ## v.0.2.1
6
+
7
+ * Fix bug when APIs includes root in json responses
8
+
9
+ ## v.0.2.0
10
+
11
+ * Add Jeckle middlewares
data/README.md CHANGED
@@ -56,7 +56,7 @@ module SomeService
56
56
  class MyResource
57
57
  include Jeckle::Resource
58
58
 
59
- default_api :some_service
59
+ api :some_service
60
60
 
61
61
  attribute :id
62
62
  end
data/examples/dribbble.rb CHANGED
@@ -9,7 +9,7 @@ end
9
9
  class Shot
10
10
  include Jeckle::Resource
11
11
 
12
- default_api :dribbble
12
+ api :dribbble
13
13
 
14
14
  attribute :id, Integer
15
15
  attribute :name, String
@@ -0,0 +1,79 @@
1
+ module Jeckle
2
+ module HTTP
3
+ def self.included(base)
4
+ base.extend Jeckle::HTTP::APIMapping
5
+ end
6
+
7
+ module APIMapping
8
+ def inherited(base)
9
+ base.class_eval do
10
+ @api_mapping = superclass.api_mapping.dup
11
+ end
12
+ end
13
+
14
+ # The name of the resource that Jeckle uses to make the request
15
+ #
16
+ # @example
17
+ #
18
+ # module Dribble
19
+ # class Shot
20
+ # include Jeckle::Resource
21
+ # end
22
+ # end
23
+ #
24
+ # Shot.resource_name # => Will request for '/shots' resource
25
+ #
26
+ # To overwrite this behaviour, rewrite the resource name method in the class:
27
+ #
28
+ # module OtherApi
29
+ # class Project
30
+ # include Jeckle::Resource
31
+ #
32
+ # def self.resource_name
33
+ # '/project'
34
+ # end
35
+ # end
36
+ # end
37
+ #
38
+ def resource_name
39
+ @resource_name ||= model_name.element.pluralize
40
+ end
41
+
42
+ # The API name that Jeckle uses to find all the api settings like domain, headers, etc.
43
+ #
44
+ # @example
45
+ #
46
+ # Jeckle.configure do |config|
47
+ # config.register :dribbble do |api|
48
+ # api.base_uri = 'http://api.dribbble.com'
49
+ # end
50
+ # end
51
+ #
52
+ # class Shot
53
+ # include Jeckle::Resource
54
+ # api :dribbble
55
+ # end
56
+ #
57
+ def api(registered_api_name)
58
+ api_mapping[:default_api] = Jeckle::Setup.registered_apis.fetch(registered_api_name)
59
+ rescue KeyError => e
60
+ raise Jeckle::NoSuchAPIError, registered_api_name
61
+ end
62
+
63
+ # @deprecated Please use {#api} instead
64
+ #
65
+ def default_api(registered_api_name)
66
+ warn "[DEPRECATION] `default_api` is deprecated. Please use `api` instead."
67
+ api(registered_api_name)
68
+ end
69
+
70
+ def api_mapping
71
+ @api_mapping ||= {}
72
+ end
73
+
74
+ def run_request(endpoint, options = {})
75
+ Jeckle::Request.run api_mapping[:default_api], endpoint, options
76
+ end
77
+ end
78
+ end
79
+ end
@@ -5,8 +5,8 @@ module Jeckle
5
5
  def initialize(api, endpoint, options = {})
6
6
  @api = api
7
7
 
8
- @method = options.delete(:method) || :get
9
- @body = options.delete(:body) if %w(post put).include?(method.to_s)
8
+ @method = options.delete(:method) || :get
9
+ @body = options.delete(:body) if %w(post put).include?(method.to_s)
10
10
  @headers = options.delete(:headers)
11
11
 
12
12
  @endpoint = endpoint
@@ -24,8 +24,8 @@ module Jeckle
24
24
  def perform_api_request
25
25
  api.connection.public_send method do |api_request|
26
26
  api_request.url endpoint
27
- api_request.params = params
28
- api_request.body = body
27
+ api_request.params = params
28
+ api_request.body = body
29
29
  api_request.headers = api_request.headers.merge(headers) if headers
30
30
  end
31
31
  end
@@ -1,50 +1,11 @@
1
1
  module Jeckle
2
2
  module Resource
3
3
  def self.included(base)
4
- base.send :include, Jeckle::Model
5
4
  base.send :include, ActiveModel::Naming
6
5
 
7
- base.send :extend, Jeckle::Resource::ClassMethods
8
- end
9
-
10
- module ClassMethods
11
- def inherited(base)
12
- base.class_eval do
13
- @api_mapping = superclass.api_mapping.dup
14
- end
15
- end
16
-
17
- def resource_name
18
- model_name.element.pluralize
19
- end
20
-
21
- def default_api(registered_api_name)
22
- api_mapping[:default_api] = Jeckle::Setup.registered_apis.fetch(registered_api_name)
23
- rescue KeyError => e
24
- raise Jeckle::NoSuchAPIError, registered_api_name
25
- end
26
-
27
- def api_mapping
28
- @api_mapping ||= {}
29
- end
30
-
31
- def find(id)
32
- endpoint = "#{resource_name}/#{id}"
33
- attributes = run_request(endpoint).response.body
34
-
35
- new attributes
36
- end
37
-
38
- def search(params = {})
39
- response = run_request(resource_name, params).response.body || []
40
- collection = response.kind_of?(Array) ? response : response[resource_name]
41
-
42
- Array(collection).collect { |attrs| new attrs }
43
- end
44
-
45
- def run_request(endpoint, options = {})
46
- Jeckle::Request.run api_mapping[:default_api], endpoint, options
47
- end
6
+ base.send :include, Jeckle::Model
7
+ base.send :include, Jeckle::HTTP
8
+ base.send :include, Jeckle::RESTActions
48
9
  end
49
10
  end
50
11
  end
@@ -0,0 +1,23 @@
1
+ module Jeckle
2
+ module RESTActions
3
+ def self.included(base)
4
+ base.send :extend, Jeckle::RESTActions::Collection
5
+ end
6
+
7
+ module Collection
8
+ def find(id)
9
+ endpoint = "#{resource_name}/#{id}"
10
+ attributes = run_request(endpoint).response.body
11
+
12
+ new attributes
13
+ end
14
+
15
+ def search(params = {})
16
+ response = run_request(resource_name, params).response.body || []
17
+ collection = response.kind_of?(Array) ? response : response[resource_name]
18
+
19
+ Array(collection).collect { |attrs| new attrs }
20
+ end
21
+ end
22
+ end
23
+ end
@@ -1,3 +1,3 @@
1
1
  module Jeckle
2
- VERSION = '0.2.1'
2
+ VERSION = '0.3.0'
3
3
  end
data/lib/jeckle.rb CHANGED
@@ -5,7 +5,7 @@ require 'virtus'
5
5
 
6
6
  require 'jeckle/version'
7
7
 
8
- %w(setup api model request resource errors).each do |file_name|
8
+ %w(setup api model request http rest_actions resource errors).each do |file_name|
9
9
  require "jeckle/#{file_name}"
10
10
  end
11
11
 
@@ -1,31 +1,33 @@
1
- Jeckle::Setup.register(:my_super_api) do |api|
2
- api.base_uri = 'http://my-super-api.com.br'
3
- api.headers = { 'Content-Type' => 'application/json' }
4
- api.logger = Logger.new(STDOUT)
5
- api.basic_auth = { username: 'steven_seagal', password: 'youAlwaysLose' }
6
- api.namespaces = { prefix: 'api', version: 'v1' }
7
- api.params = { hello: 'world' }
8
- api.open_timeout = 2
9
- api.read_timeout = 5
1
+ Jeckle.configure do |config|
2
+ config.register :my_super_api do |api|
3
+ api.base_uri = 'http://my-super-api.com.br'
4
+ api.headers = { 'Content-Type' => 'application/json' }
5
+ api.logger = Logger.new(STDOUT)
6
+ api.basic_auth = { username: 'steven_seagal', password: 'youAlwaysLose' }
7
+ api.namespaces = { prefix: 'api', version: 'v1' }
8
+ api.params = { hello: 'world' }
9
+ api.open_timeout = 2
10
+ api.read_timeout = 5
10
11
 
11
- api.middlewares do
12
- request :json
13
- response :json
14
- response :raise_error
12
+ api.middlewares do
13
+ request :json
14
+ response :json
15
+ response :raise_error
16
+ end
15
17
  end
16
- end
17
18
 
18
- Jeckle::Setup.register(:another_api) do |api|
19
- api.base_uri = 'http://another-api.com.br'
20
- api.headers = { 'Content-Type' => 'application/json' }
21
- api.logger = Logger.new(STDOUT)
22
- api.basic_auth = { username: 'heisenberg', password: 'metaAfetaAMina' }
23
- api.namespaces = { prefix: 'api', version: 'v5' }
24
- api.params = { hi: 'there' }
19
+ config.register :another_api do |api|
20
+ api.base_uri = 'http://another-api.com.br'
21
+ api.headers = { 'Content-Type' => 'application/json' }
22
+ api.logger = Logger.new(STDOUT)
23
+ api.basic_auth = { username: 'heisenberg', password: 'metaAfetaAMina' }
24
+ api.namespaces = { prefix: 'api', version: 'v5' }
25
+ api.params = { hi: 'there' }
25
26
 
26
- api.middlewares do
27
- request :json
28
- response :json
29
- response :raise_error
27
+ api.middlewares do
28
+ request :json
29
+ response :json
30
+ response :raise_error
31
+ end
30
32
  end
31
33
  end
@@ -1,7 +1,7 @@
1
1
  class FakeResource
2
2
  include Jeckle::Resource
3
3
 
4
- default_api :my_super_api
4
+ api :my_super_api
5
5
 
6
6
  attribute :id, Integer
7
7
  end
@@ -0,0 +1,63 @@
1
+ require 'spec_helper'
2
+
3
+ RSpec.describe Jeckle::HTTP do
4
+ describe '.resource_name' do
5
+ it 'returns resource name based on class name' do
6
+ expect(FakeResource.resource_name).to eq 'fake_resources'
7
+ end
8
+
9
+ context 'when resource class is namespaced' do
10
+ before do
11
+ MySuperApi = Module.new
12
+ MySuperApi::FakeResource = Class.new(::FakeResource)
13
+ end
14
+
15
+ it 'ignores namespace' do
16
+ expect(MySuperApi::FakeResource.resource_name).to eq 'fake_resources'
17
+ end
18
+ end
19
+ end
20
+
21
+ describe '.api_mapping' do
22
+ it 'returns a hash containing default api' do
23
+ expect(FakeResource.api_mapping).to match(
24
+ default_api: an_instance_of(Jeckle::API)
25
+ )
26
+ end
27
+
28
+ context 'when resource is inherited' do
29
+ let(:inherited_class) { Class.new(FakeResource) }
30
+
31
+ it "contains the parent's api_mapping" do
32
+ expect(inherited_class.api_mapping).to eq FakeResource.api_mapping
33
+ end
34
+
35
+ context 'when api_mapping is changed' do
36
+ it "does not affect the parent" do
37
+ inherited_class.api :another_api
38
+
39
+ expect(FakeResource.api_mapping).not_to eq inherited_class.api_mapping
40
+ expect(FakeResource.api_mapping[:default_api]).to eq Jeckle::Setup.registered_apis[:my_super_api]
41
+ end
42
+ end
43
+ end
44
+ end
45
+
46
+ describe '.default_api' do
47
+ context 'when defining a registered API via Jeckle::Setup' do
48
+ it 'returns the assigned API' do
49
+ expect(FakeResource.api :my_super_api).to be_kind_of Jeckle::API
50
+ end
51
+
52
+ it 'assigns API do api_mapping' do
53
+ expect(FakeResource.api_mapping).to have_key :default_api
54
+ end
55
+ end
56
+
57
+ context 'when defining an inexistent API' do
58
+ it 'raises NoSuchAPIError' do
59
+ expect { FakeResource.api :unknown_api }.to raise_error Jeckle::NoSuchAPIError
60
+ end
61
+ end
62
+ end
63
+ end
@@ -3,8 +3,6 @@ require 'spec_helper'
3
3
  RSpec.describe Jeckle::Resource do
4
4
  subject(:fake_resource) { FakeResource.new }
5
5
 
6
- let(:api) { FakeResource.api_mapping[:default_api] }
7
-
8
6
  it 'includes jeckle/model' do
9
7
  expect(FakeResource.ancestors).to include Jeckle::Model
10
8
  end
@@ -13,131 +11,11 @@ RSpec.describe Jeckle::Resource do
13
11
  expect(FakeResource.ancestors).to include ActiveModel::Naming
14
12
  end
15
13
 
16
- describe '.resource_name' do
17
- it 'returns resource name based on class name' do
18
- expect(FakeResource.resource_name).to eq 'fake_resources'
19
- end
20
-
21
- context 'when resource class is namespaced' do
22
- before do
23
- MySuperApi = Module.new
24
- MySuperApi::FakeResource = Class.new(::FakeResource)
25
- end
26
-
27
- it 'ignores namespace' do
28
- expect(MySuperApi::FakeResource.resource_name).to eq 'fake_resources'
29
- end
30
- end
31
- end
32
-
33
- describe '.api_mapping' do
34
- it 'returns a hash containing default api' do
35
- expect(FakeResource.api_mapping).to match(
36
- default_api: an_instance_of(Jeckle::API)
37
- )
38
- end
39
-
40
- context 'when resource is inherited' do
41
- let(:inherited_class) { Class.new(FakeResource) }
42
-
43
- it "contains the parent's api_mapping" do
44
- expect(inherited_class.api_mapping).to eq FakeResource.api_mapping
45
- end
46
-
47
- context 'when api_mapping is changed' do
48
- it "does not affect the parent" do
49
- inherited_class.default_api :another_api
50
-
51
- expect(FakeResource.api_mapping).not_to eq inherited_class.api_mapping
52
- expect(FakeResource.api_mapping[:default_api]).to eq Jeckle::Setup.registered_apis[:my_super_api]
53
- end
54
- end
55
- end
56
- end
57
-
58
- describe '.default_api' do
59
- context 'when defining a registered API via Jeckle::Setup' do
60
- it 'returns the assigned API' do
61
- expect(FakeResource.default_api :my_super_api).to be_kind_of Jeckle::API
62
- end
63
-
64
- it 'assigns API do api_mapping' do
65
- expect(FakeResource.api_mapping).to have_key :default_api
66
- end
67
- end
68
-
69
- context 'when defining an inexistent API' do
70
- it 'raises NoSuchAPIError' do
71
- expect { FakeResource.default_api :unknown_api }.to raise_error Jeckle::NoSuchAPIError
72
- end
73
- end
14
+ it 'includes jeckle http' do
15
+ expect(FakeResource.ancestors).to include Jeckle::HTTP
74
16
  end
75
17
 
76
- describe '.find' do
77
- let(:fake_request) { OpenStruct.new response: OpenStruct.new(body: { id: 1001 }) }
78
-
79
- it 'calls default API connection with GET' do
80
- expect(Jeckle::Request).to receive(:run)
81
- .with(api, 'fake_resources/1001', {}).and_return(fake_request)
82
-
83
- FakeResource.find 1001
84
- end
85
-
86
- it 'returns an instance of resource' do
87
- allow(Jeckle::Request).to receive(:run).and_return(fake_request)
88
-
89
- expect(FakeResource.find 1001).to be_an_instance_of(FakeResource)
90
- end
91
- end
92
-
93
- describe '.search' do
94
- let(:fake_request) { OpenStruct.new response: OpenStruct.new(body: body) }
95
-
96
- let(:query) { { name: 'cocada' } }
97
-
98
- context 'when there are results WITHOUT root node' do
99
- let(:body) { [{ id: 1001 }, { id: 1002 }] }
100
-
101
- it 'calls default API connection with GET and search params' do
102
- expect(Jeckle::Request).to receive(:run)
103
- .with(api, 'fake_resources', query).and_return(fake_request)
104
-
105
- FakeResource.search query
106
- end
107
-
108
- it 'returns an Array of resources' do
109
- allow(Jeckle::Request).to receive(:run).and_return(fake_request)
110
-
111
- expect(FakeResource.search query).to match [
112
- an_instance_of(FakeResource),
113
- an_instance_of(FakeResource)
114
- ]
115
- end
116
- end
117
-
118
- context 'when there are results WITH root node' do
119
- let(:body) do
120
- { 'fake_resources' => [{ id: 1001 }, { id: 1002 } ] }
121
- end
122
-
123
- it 'returns an Array of resources' do
124
- allow(Jeckle::Request).to receive(:run).and_return(fake_request)
125
-
126
- expect(FakeResource.search query).to match [
127
- an_instance_of(FakeResource),
128
- an_instance_of(FakeResource)
129
- ]
130
- end
131
- end
132
-
133
- context 'when there are no results' do
134
- let(:fake_request) { OpenStruct.new response: OpenStruct.new(body: nil) }
135
-
136
- it 'returns an empty Array' do
137
- allow(Jeckle::Request).to receive(:run).and_return(fake_request)
138
-
139
- expect(FakeResource.search query).to match []
140
- end
141
- end
18
+ it 'includes jeckle rest actions' do
19
+ expect(FakeResource.ancestors).to include Jeckle::RESTActions
142
20
  end
143
21
  end
@@ -0,0 +1,73 @@
1
+ require 'spec_helper'
2
+
3
+ RSpec.describe Jeckle::RESTActions do
4
+ let(:api) { FakeResource.api_mapping[:default_api] }
5
+
6
+ describe '.find' do
7
+ let(:fake_request) { OpenStruct.new response: OpenStruct.new(body: { id: 1001 }) }
8
+
9
+ it 'calls default API connection with GET' do
10
+ expect(Jeckle::Request).to receive(:run)
11
+ .with(api, 'fake_resources/1001', {}).and_return(fake_request)
12
+
13
+ FakeResource.find 1001
14
+ end
15
+
16
+ it 'returns an instance of resource' do
17
+ allow(Jeckle::Request).to receive(:run).and_return(fake_request)
18
+
19
+ expect(FakeResource.find 1001).to be_an_instance_of(FakeResource)
20
+ end
21
+ end
22
+
23
+ describe '.search' do
24
+ let(:fake_request) { OpenStruct.new response: OpenStruct.new(body: body) }
25
+
26
+ let(:query) { { name: 'cocada' } }
27
+
28
+ context 'when there are results WITHOUT root node' do
29
+ let(:body) { [{ id: 1001 }, { id: 1002 }] }
30
+
31
+ it 'calls default API connection with GET and search params' do
32
+ expect(Jeckle::Request).to receive(:run)
33
+ .with(api, 'fake_resources', query).and_return(fake_request)
34
+
35
+ FakeResource.search query
36
+ end
37
+
38
+ it 'returns an Array of resources' do
39
+ allow(Jeckle::Request).to receive(:run).and_return(fake_request)
40
+
41
+ expect(FakeResource.search query).to match [
42
+ an_instance_of(FakeResource),
43
+ an_instance_of(FakeResource)
44
+ ]
45
+ end
46
+ end
47
+
48
+ context 'when there are results WITH root node' do
49
+ let(:body) do
50
+ { 'fake_resources' => [{ id: 1001 }, { id: 1002 } ] }
51
+ end
52
+
53
+ it 'returns an Array of resources' do
54
+ allow(Jeckle::Request).to receive(:run).and_return(fake_request)
55
+
56
+ expect(FakeResource.search query).to match [
57
+ an_instance_of(FakeResource),
58
+ an_instance_of(FakeResource)
59
+ ]
60
+ end
61
+ end
62
+
63
+ context 'when there are no results' do
64
+ let(:fake_request) { OpenStruct.new response: OpenStruct.new(body: nil) }
65
+
66
+ it 'returns an empty Array' do
67
+ allow(Jeckle::Request).to receive(:run).and_return(fake_request)
68
+
69
+ expect(FakeResource.search query).to match []
70
+ end
71
+ end
72
+ end
73
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: jeckle
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.1
4
+ version: 0.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Tomas D'Stefano
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2014-10-16 00:00:00.000000000 Z
12
+ date: 2014-10-22 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: activemodel
@@ -135,6 +135,7 @@ files:
135
135
  - .rspec
136
136
  - .travis.yml
137
137
  - Gemfile
138
+ - History.markdown
138
139
  - LICENSE.txt
139
140
  - README.md
140
141
  - Rakefile
@@ -143,18 +144,22 @@ files:
143
144
  - lib/jeckle.rb
144
145
  - lib/jeckle/api.rb
145
146
  - lib/jeckle/errors.rb
147
+ - lib/jeckle/http.rb
146
148
  - lib/jeckle/model.rb
147
149
  - lib/jeckle/request.rb
148
150
  - lib/jeckle/resource.rb
151
+ - lib/jeckle/rest_actions.rb
149
152
  - lib/jeckle/setup.rb
150
153
  - lib/jeckle/version.rb
151
154
  - spec/fixtures/jeckle_config.rb
152
155
  - spec/fixtures/models/fake_model.rb
153
156
  - spec/fixtures/resources/fake_resource.rb
154
157
  - spec/jeckle/api_spec.rb
158
+ - spec/jeckle/http_spec.rb
155
159
  - spec/jeckle/model_spec.rb
156
160
  - spec/jeckle/request_spec.rb
157
161
  - spec/jeckle/resource_spec.rb
162
+ - spec/jeckle/rest_actions_spec.rb
158
163
  - spec/jeckle/setup_spec.rb
159
164
  - spec/spec_helper.rb
160
165
  - spec/support/shared_examples.rb
@@ -187,9 +192,11 @@ test_files:
187
192
  - spec/fixtures/models/fake_model.rb
188
193
  - spec/fixtures/resources/fake_resource.rb
189
194
  - spec/jeckle/api_spec.rb
195
+ - spec/jeckle/http_spec.rb
190
196
  - spec/jeckle/model_spec.rb
191
197
  - spec/jeckle/request_spec.rb
192
198
  - spec/jeckle/resource_spec.rb
199
+ - spec/jeckle/rest_actions_spec.rb
193
200
  - spec/jeckle/setup_spec.rb
194
201
  - spec/spec_helper.rb
195
202
  - spec/support/shared_examples.rb