rom-http 0.1.0 → 0.1.1
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.
- checksums.yaml +4 -4
- data/.rubocop.yml +3 -0
- data/.rubocop_todo.yml +8 -2
- data/CHANGELOG.md +13 -0
- data/README.md +78 -0
- data/lib/rom/http/dataset.rb +41 -19
- data/lib/rom/http/error.rb +0 -12
- data/lib/rom/http/gateway.rb +10 -4
- data/lib/rom/http/version.rb +1 -1
- data/spec/shared/command_behaviour.rb +2 -2
- data/spec/unit/rom/http/dataset_spec.rb +104 -20
- data/spec/unit/rom/http/gateway_spec.rb +37 -3
- metadata +3 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 0a5d2946beb3f147e7b8e09a390d1db24006b131
|
4
|
+
data.tar.gz: 3780c786affbb10b47987b63a7344e6765ab4964
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 1d12b8a1740657967ed774d8bfd61af0f738123ca92e857a7eeb5a82deb53c4c1defeca7229216e636abbb3f3c3f4ce51de211b2dd9bc2822f41f597ec2f6f5f
|
7
|
+
data.tar.gz: 2b39120ff86cf082e57395c2b188b40acd72e746d5d26a567b4d89bad4e7cb8dacd518889450d208b7342956ce378ffb0519af828f60bf2236e115f612523cc7
|
data/.rubocop.yml
CHANGED
data/.rubocop_todo.yml
CHANGED
@@ -1,6 +1,12 @@
|
|
1
|
-
# This configuration was generated by
|
2
|
-
#
|
1
|
+
# This configuration was generated by
|
2
|
+
# `rubocop --auto-gen-config`
|
3
|
+
# on 2015-09-03 20:59:57 +0100 using RuboCop version 0.33.0.
|
3
4
|
# The point is for the user to remove these configuration records
|
4
5
|
# one by one as the offenses are removed from the code base.
|
5
6
|
# Note that changes in the inspected code, or installation of new
|
6
7
|
# versions of RuboCop, may require this file to be generated again.
|
8
|
+
|
9
|
+
# Offense count: 1
|
10
|
+
# Configuration parameters: CountComments.
|
11
|
+
Metrics/ClassLength:
|
12
|
+
Max: 104
|
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,16 @@
|
|
1
|
+
# v0.1.1 2015-09-03
|
2
|
+
### Added
|
3
|
+
|
4
|
+
- `ROM::HTTP::Dataset` macros for setting `default_request_handler` and `default_response_handler` (AMHOL)
|
5
|
+
|
6
|
+
### Changed
|
7
|
+
|
8
|
+
- `ROM::HTTP::Gateway` tries to load the `Dataset` class lazily from the same namespace that the `Gateway` is defined in, with a fallback to `ROM::HTTP::Dataset`, making extending easier (AMHOL)
|
9
|
+
- `ROM::HTTP::Gateway` no longer raises errors on missing configuration keys, these are now raised late in `Dataset` - this was to allow for the implementation of `default_request_handler` and `default_response_handler` (AMHOL)
|
10
|
+
- `ROM::HTTP::Dataset` now uses `ROM::Options` from `rom-support`, adding typechecking to options and making it easier to define additional options in extensions
|
11
|
+
|
12
|
+
[Compare v0.1.0...v0.1.1](https://github.com/rom-rb/rom-http/compare/v0.1.0...v0.1.1)
|
13
|
+
|
1
14
|
# v0.1.0 2015-08-19
|
2
15
|
|
3
16
|
First public release \o/
|
data/README.md
CHANGED
@@ -62,3 +62,81 @@ container = rom.finalize.env
|
|
62
62
|
container.relation(:users).by_id(1).to_a
|
63
63
|
# => GET http://jsonplaceholder.typicode.com/users/1 [ Accept: application/json ]
|
64
64
|
```
|
65
|
+
|
66
|
+
### Extending
|
67
|
+
|
68
|
+
```ruby
|
69
|
+
require 'json'
|
70
|
+
require 'uri'
|
71
|
+
require 'net/http'
|
72
|
+
|
73
|
+
module ROM
|
74
|
+
module MyAdapter
|
75
|
+
class Dataset < ROM::HTTP::Dataset
|
76
|
+
default_request_handler ->(dataset) do
|
77
|
+
uri = URI(dataset.uri)
|
78
|
+
uri.path = "/#{dataset.name}/#{dataset.path}"
|
79
|
+
uri.query = URI.encode_www_form(dataset.params)
|
80
|
+
|
81
|
+
http = Net::HTTP.new(uri.host, uri.port)
|
82
|
+
request_klass = Net::HTTP.const_get(ROM::Inflector.classify(dataset.request_method))
|
83
|
+
|
84
|
+
request = request_klass.new(uri.request_uri)
|
85
|
+
dataset.headers.each_with_object(request) do |(header, value), request|
|
86
|
+
request[header.to_s] = value
|
87
|
+
end
|
88
|
+
|
89
|
+
response = http.request(request)
|
90
|
+
end
|
91
|
+
|
92
|
+
default_response_handler ->(response, dataset) do
|
93
|
+
Array([JSON.parse(response.body)]).flatten
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
97
|
+
class Gateway < ROM::HTTP::Gateway; end
|
98
|
+
|
99
|
+
class Relation < ROM::HTTP::Relation
|
100
|
+
adapter :my_adapter
|
101
|
+
end
|
102
|
+
|
103
|
+
module Commands
|
104
|
+
class Create < ROM::HTTP::Commands::Create
|
105
|
+
adapter :my_adapter
|
106
|
+
end
|
107
|
+
|
108
|
+
class Update < ROM::HTTP::Commands::Create
|
109
|
+
adapter :my_adapter
|
110
|
+
end
|
111
|
+
|
112
|
+
class Delete < ROM::HTTP::Commands::Create
|
113
|
+
adapter :my_adapter
|
114
|
+
end
|
115
|
+
end
|
116
|
+
end
|
117
|
+
end
|
118
|
+
|
119
|
+
ROM.register_adapter(:my_adapter, ROM::MyAdapter)
|
120
|
+
|
121
|
+
rom = ROM::Environment.new
|
122
|
+
rom.setup(:my_adapter, {
|
123
|
+
uri: 'http://jsonplaceholder.typicode.com',
|
124
|
+
headers: {
|
125
|
+
Accept: 'application/json'
|
126
|
+
}
|
127
|
+
})
|
128
|
+
|
129
|
+
class Users < ROM::Relation[:my_adapter]
|
130
|
+
dataset :users
|
131
|
+
|
132
|
+
def by_id(id)
|
133
|
+
with_path(id.to_s)
|
134
|
+
end
|
135
|
+
end
|
136
|
+
|
137
|
+
rom.register_relation(Users)
|
138
|
+
|
139
|
+
container = rom.finalize.env
|
140
|
+
container.relation(:users).by_id(1).to_a
|
141
|
+
# => GET http://jsonplaceholder.typicode.com/users/1 [ Accept: application/json ]
|
142
|
+
```
|
data/lib/rom/http/dataset.rb
CHANGED
@@ -3,20 +3,34 @@ module ROM
|
|
3
3
|
class Dataset
|
4
4
|
include Enumerable
|
5
5
|
include Equalizer.new(:config, :options)
|
6
|
+
include ROM::Options
|
6
7
|
|
7
|
-
attr_reader :config
|
8
|
+
attr_reader :config
|
9
|
+
|
10
|
+
option :request_method, type: ::Symbol, default: :get, reader: true
|
11
|
+
option :path, type: ::String, default: ''
|
12
|
+
option :params, type: ::Hash, default: {}, reader: true
|
13
|
+
option :headers, type: ::Hash, default: {}
|
14
|
+
|
15
|
+
class << self
|
16
|
+
def default_request_handler(handler = Undefined)
|
17
|
+
return @default_request_handler if Undefined === handler
|
18
|
+
@default_request_handler = handler
|
19
|
+
end
|
20
|
+
|
21
|
+
def default_response_handler(handler = Undefined)
|
22
|
+
return @default_response_handler if Undefined === handler
|
23
|
+
@default_response_handler = handler
|
24
|
+
end
|
25
|
+
end
|
8
26
|
|
9
27
|
def initialize(config, options = {})
|
10
28
|
@config = config
|
11
|
-
|
12
|
-
request_method: :get,
|
13
|
-
path: '',
|
14
|
-
params: {}
|
15
|
-
}.merge(options)
|
29
|
+
super(options)
|
16
30
|
end
|
17
31
|
|
18
32
|
def uri
|
19
|
-
config
|
33
|
+
config.fetch(:uri) { fail Error, ':uri configuration missing' }
|
20
34
|
end
|
21
35
|
|
22
36
|
def headers
|
@@ -35,16 +49,8 @@ module ROM
|
|
35
49
|
'/' + path
|
36
50
|
end
|
37
51
|
|
38
|
-
def request_method
|
39
|
-
options[:request_method]
|
40
|
-
end
|
41
|
-
|
42
|
-
def params
|
43
|
-
options[:params]
|
44
|
-
end
|
45
|
-
|
46
52
|
def with_headers(headers)
|
47
|
-
|
53
|
+
__new__(config, options.merge(headers: headers))
|
48
54
|
end
|
49
55
|
|
50
56
|
def add_header(header, value)
|
@@ -52,7 +58,7 @@ module ROM
|
|
52
58
|
end
|
53
59
|
|
54
60
|
def with_options(opts)
|
55
|
-
|
61
|
+
__new__(config, options.merge(opts))
|
56
62
|
end
|
57
63
|
|
58
64
|
def with_path(path)
|
@@ -103,11 +109,27 @@ module ROM
|
|
103
109
|
private
|
104
110
|
|
105
111
|
def response_handler
|
106
|
-
config
|
112
|
+
config.fetch(:response_handler, default_response_handler).tap do |response_handler|
|
113
|
+
fail Error, ':response_handler configuration missing' if response_handler.nil?
|
114
|
+
end
|
107
115
|
end
|
108
116
|
|
109
117
|
def request_handler
|
110
|
-
config
|
118
|
+
config.fetch(:request_handler, default_request_handler).tap do |request_handler|
|
119
|
+
fail Error, ':response_handler configuration missing' if request_handler.nil?
|
120
|
+
end
|
121
|
+
end
|
122
|
+
|
123
|
+
def default_response_handler
|
124
|
+
self.class.default_response_handler
|
125
|
+
end
|
126
|
+
|
127
|
+
def default_request_handler
|
128
|
+
self.class.default_request_handler
|
129
|
+
end
|
130
|
+
|
131
|
+
def __new__(*args, &block)
|
132
|
+
self.class.new(*args, &block)
|
111
133
|
end
|
112
134
|
end
|
113
135
|
end
|
data/lib/rom/http/error.rb
CHANGED
@@ -1,17 +1,5 @@
|
|
1
1
|
module ROM
|
2
2
|
module HTTP
|
3
3
|
Error = Class.new(StandardError)
|
4
|
-
|
5
|
-
class GatewayConfigurationError < Error
|
6
|
-
def initialize(missing_keys)
|
7
|
-
if missing_keys.length > 1
|
8
|
-
msg = "Missing #{missing_keys[0..-1].join(', ')} and #{missing_keys.last}"
|
9
|
-
else
|
10
|
-
msg = "Missing #{missing_keys.last}"
|
11
|
-
end
|
12
|
-
|
13
|
-
super(msg + ' in ROM::HTTP::Gateway configuration')
|
14
|
-
end
|
15
|
-
end
|
16
4
|
end
|
17
5
|
end
|
data/lib/rom/http/gateway.rb
CHANGED
@@ -8,9 +8,6 @@ module ROM
|
|
8
8
|
private :datasets, :config
|
9
9
|
|
10
10
|
def initialize(config)
|
11
|
-
missing_keys = [:uri, :request_handler, :response_handler] - config.keys
|
12
|
-
fail GatewayConfigurationError, missing_keys unless missing_keys.empty?
|
13
|
-
|
14
11
|
@datasets = ThreadSafe::Cache.new
|
15
12
|
@config = config
|
16
13
|
end
|
@@ -20,12 +17,21 @@ module ROM
|
|
20
17
|
end
|
21
18
|
|
22
19
|
def dataset(name)
|
23
|
-
|
20
|
+
dataset_klass = namespace.const_defined?(:Dataset) ? namespace.const_get(:Dataset) : Dataset
|
21
|
+
datasets[name] = dataset_klass.new(config.merge(name: name))
|
24
22
|
end
|
25
23
|
|
26
24
|
def dataset?(name)
|
27
25
|
datasets.key?(name)
|
28
26
|
end
|
27
|
+
|
28
|
+
private
|
29
|
+
|
30
|
+
def namespace
|
31
|
+
self.class.to_s[/(.*)(?=::)/].split('::').inject(::Object) do |constant, const_name|
|
32
|
+
constant.const_get(const_name)
|
33
|
+
end
|
34
|
+
end
|
29
35
|
end
|
30
36
|
end
|
31
37
|
end
|
data/lib/rom/http/version.rb
CHANGED
@@ -1,10 +1,10 @@
|
|
1
1
|
shared_examples_for 'a command' do
|
2
2
|
describe '#method_missing' do
|
3
3
|
it 'forwards to relation and wraps response if it returned another relation' do
|
4
|
-
new_command = command.with_params(
|
4
|
+
new_command = command.with_params({})
|
5
5
|
|
6
6
|
expect(new_command).to be_instance_of(command.class)
|
7
|
-
expect(new_command.relation).to eq(command.with_params(
|
7
|
+
expect(new_command.relation).to eq(command.with_params({}).relation)
|
8
8
|
end
|
9
9
|
|
10
10
|
it 'returns original response if it was not a relation' do
|
@@ -1,5 +1,6 @@
|
|
1
1
|
RSpec.describe ROM::HTTP::Dataset do
|
2
|
-
let(:
|
2
|
+
let(:klass) { ROM::HTTP::Dataset }
|
3
|
+
let(:dataset) { klass.new(config, options) }
|
3
4
|
let(:config) do
|
4
5
|
{
|
5
6
|
uri: uri,
|
@@ -51,33 +52,74 @@ RSpec.describe ROM::HTTP::Dataset do
|
|
51
52
|
is_expected.to eq(
|
52
53
|
request_method: :get,
|
53
54
|
path: '',
|
54
|
-
params: {}
|
55
|
+
params: {},
|
56
|
+
headers: {}
|
55
57
|
)
|
56
58
|
end
|
57
59
|
end
|
58
60
|
end
|
59
61
|
end
|
60
62
|
|
61
|
-
describe '
|
62
|
-
|
63
|
+
describe '.default_request_handler' do
|
64
|
+
before do
|
65
|
+
module Test
|
66
|
+
class Dataset < ROM::HTTP::Dataset; end
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
context 'when no default_request_handler set' do
|
71
|
+
it 'returns nil' do
|
72
|
+
expect(klass.default_request_handler).to be nil
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
context 'when default_request_handler set' do
|
77
|
+
before do
|
78
|
+
Test::Dataset.default_request_handler(request_handler)
|
79
|
+
end
|
80
|
+
|
81
|
+
it 'returns the default request handler' do
|
82
|
+
expect(Test::Dataset.default_request_handler).to eq request_handler
|
83
|
+
end
|
84
|
+
end
|
85
|
+
end
|
63
86
|
|
64
|
-
|
65
|
-
|
87
|
+
describe '.default_response_handler' do
|
88
|
+
before do
|
89
|
+
module Test
|
90
|
+
class Dataset < ROM::HTTP::Dataset; end
|
91
|
+
end
|
92
|
+
end
|
66
93
|
|
67
|
-
|
94
|
+
context 'when no default_response_handler set' do
|
95
|
+
it 'returns nil' do
|
96
|
+
expect(klass.default_response_handler).to be nil
|
97
|
+
end
|
68
98
|
end
|
69
99
|
|
70
|
-
context '
|
71
|
-
|
72
|
-
|
100
|
+
context 'when default_response_handler set' do
|
101
|
+
before do
|
102
|
+
Test::Dataset.default_response_handler(response_handler)
|
73
103
|
end
|
74
104
|
|
75
|
-
it
|
105
|
+
it 'returns the default response handler' do
|
106
|
+
expect(Test::Dataset.default_response_handler).to eq response_handler
|
107
|
+
end
|
76
108
|
end
|
77
109
|
end
|
78
110
|
|
79
111
|
describe '#uri' do
|
80
|
-
|
112
|
+
context 'when no uri configured' do
|
113
|
+
let(:config) { {} }
|
114
|
+
|
115
|
+
it do
|
116
|
+
expect { dataset.uri }.to raise_error(ROM::HTTP::Error)
|
117
|
+
end
|
118
|
+
end
|
119
|
+
|
120
|
+
context 'when uri configured' do
|
121
|
+
it { expect(dataset.uri).to eq(uri) }
|
122
|
+
end
|
81
123
|
end
|
82
124
|
|
83
125
|
describe '#headers' do
|
@@ -288,7 +330,8 @@ RSpec.describe ROM::HTTP::Dataset do
|
|
288
330
|
path: '',
|
289
331
|
params: {
|
290
332
|
name: name
|
291
|
-
}
|
333
|
+
},
|
334
|
+
headers: {}
|
292
335
|
)
|
293
336
|
end
|
294
337
|
it { is_expected.to_not be(dataset) }
|
@@ -458,15 +501,56 @@ RSpec.describe ROM::HTTP::Dataset do
|
|
458
501
|
let(:response) { double }
|
459
502
|
let(:result) { double }
|
460
503
|
|
461
|
-
|
462
|
-
|
463
|
-
|
504
|
+
context 'when request_handler and response_handler configured' do
|
505
|
+
before do
|
506
|
+
allow(request_handler).to receive(:call).and_return(response)
|
507
|
+
allow(response_handler).to receive(:call).and_return(result)
|
508
|
+
end
|
509
|
+
|
510
|
+
subject! { dataset.response }
|
511
|
+
|
512
|
+
it { expect(request_handler).to have_received(:call).with(dataset) }
|
513
|
+
it { expect(response_handler).to have_received(:call).with(response, dataset) }
|
514
|
+
it { is_expected.to eq(result) }
|
464
515
|
end
|
465
516
|
|
466
|
-
|
517
|
+
context 'when request_handler and response_handler configured' do
|
518
|
+
let(:klass) { Test::Dataset }
|
519
|
+
let(:config) { {} }
|
520
|
+
|
521
|
+
before do
|
522
|
+
module Test
|
523
|
+
class Dataset < ROM::HTTP::Dataset; end
|
524
|
+
end
|
525
|
+
|
526
|
+
Test::Dataset.default_request_handler(request_handler)
|
527
|
+
Test::Dataset.default_response_handler(response_handler)
|
528
|
+
|
529
|
+
allow(request_handler).to receive(:call).and_return(response)
|
530
|
+
allow(response_handler).to receive(:call).and_return(result)
|
531
|
+
end
|
532
|
+
|
533
|
+
subject! { dataset.response }
|
467
534
|
|
468
|
-
|
469
|
-
|
470
|
-
|
535
|
+
it { expect(request_handler).to have_received(:call).with(dataset) }
|
536
|
+
it { expect(response_handler).to have_received(:call).with(response, dataset) }
|
537
|
+
it { is_expected.to eq(result) }
|
538
|
+
end
|
539
|
+
|
540
|
+
context 'when no request_handler configured and no default set' do
|
541
|
+
let(:config) { { response_handler: response_handler } }
|
542
|
+
|
543
|
+
it do
|
544
|
+
expect { dataset.response }.to raise_error(ROM::HTTP::Error)
|
545
|
+
end
|
546
|
+
end
|
547
|
+
|
548
|
+
context 'when no response_handler configured and no default set' do
|
549
|
+
let(:config) { { request_handler: request_handler } }
|
550
|
+
|
551
|
+
it do
|
552
|
+
expect { dataset.response }.to raise_error(ROM::HTTP::Error)
|
553
|
+
end
|
554
|
+
end
|
471
555
|
end
|
472
556
|
end
|
@@ -29,9 +29,43 @@ RSpec.describe ROM::HTTP::Gateway do
|
|
29
29
|
end
|
30
30
|
end
|
31
31
|
|
32
|
-
describe '
|
33
|
-
|
34
|
-
|
32
|
+
describe '#dataset' do
|
33
|
+
subject { gateway.dataset(:name) }
|
34
|
+
|
35
|
+
context 'when extended' do
|
36
|
+
let(:gateway) { Test::Gateway.new({}) }
|
37
|
+
|
38
|
+
before do
|
39
|
+
module Test
|
40
|
+
class Gateway < ROM::HTTP::Gateway; end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
context 'when no Dataset defined in the same namespace' do
|
45
|
+
it 'returns ROM::HTTP::Dataset' do
|
46
|
+
is_expected.to be_kind_of(ROM::HTTP::Dataset)
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
context 'when Dataset defined in the same namespace' do
|
51
|
+
before do
|
52
|
+
module Test
|
53
|
+
class Dataset < ROM::HTTP::Dataset; end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
it 'returns ROM::HTTP::Dataset' do
|
58
|
+
is_expected.to be_kind_of(Test::Dataset)
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
context 'when not extended' do
|
64
|
+
let(:gateway) { ROM::HTTP::Gateway.new({}) }
|
65
|
+
|
66
|
+
it 'returns ROM::HTTP::Dataset' do
|
67
|
+
is_expected.to be_kind_of(ROM::HTTP::Dataset)
|
68
|
+
end
|
35
69
|
end
|
36
70
|
end
|
37
71
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: rom-http
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Piotr Solnica
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2015-
|
12
|
+
date: 2015-09-03 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: rom
|
@@ -172,7 +172,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
172
172
|
version: '0'
|
173
173
|
requirements: []
|
174
174
|
rubyforge_project:
|
175
|
-
rubygems_version: 2.4.5
|
175
|
+
rubygems_version: 2.4.5.1
|
176
176
|
signing_key:
|
177
177
|
specification_version: 4
|
178
178
|
summary: HTTP support for ROM
|