rom-http 0.1.0 → 0.1.1

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: c7d3ff1f6d9c603d8c87aab168b3ed4cc14cf0e6
4
- data.tar.gz: ba29c82d3e73f6055431e1d22c00eec803e41af0
3
+ metadata.gz: 0a5d2946beb3f147e7b8e09a390d1db24006b131
4
+ data.tar.gz: 3780c786affbb10b47987b63a7344e6765ab4964
5
5
  SHA512:
6
- metadata.gz: d4e0eafcd6cd8061f8c8c356b6e4deed06aa03f16ec98cc17e1c686a0f385c354971410728e9093114e4ed020202bcfdc61b2db001ce214aa2bd2868ae6a0086
7
- data.tar.gz: 1480059baaaa7390b255eb2a7c057a4073ac4eb71c76444eceaaa89cac905ca54913d6010d8f24c6bf94fe0300a8e2f312d2c4e0fe51baee86b1fc57f36323b2
6
+ metadata.gz: 1d12b8a1740657967ed774d8bfd61af0f738123ca92e857a7eeb5a82deb53c4c1defeca7229216e636abbb3f3c3f4ce51de211b2dd9bc2822f41f597ec2f6f5f
7
+ data.tar.gz: 2b39120ff86cf082e57395c2b188b40acd72e746d5d26a567b4d89bad4e7cb8dacd518889450d208b7342956ce378ffb0519af828f60bf2236e115f612523cc7
@@ -4,6 +4,9 @@ inherit_from: .rubocop_todo.yml
4
4
  Metrics/LineLength:
5
5
  Max: 100
6
6
 
7
+ Style/CaseEquality:
8
+ Enabled: false
9
+
7
10
  # No need to handle LoadError in Rakefile
8
11
  Lint/HandleExceptions:
9
12
  Exclude:
@@ -1,6 +1,12 @@
1
- # This configuration was generated by `rubocop --auto-gen-config`
2
- # on 2015-08-05 23:05:48 +0100 using RuboCop version 0.32.0.
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
@@ -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
+ ```
@@ -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, :options
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
- @options = {
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[:uri]
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
- self.class.new(config, options.merge(headers: headers))
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
- self.class.new(config, options.merge(opts))
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[:response_handler]
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[:request_handler]
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
@@ -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
@@ -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
- datasets[name] = Dataset.new(config.merge(name: name))
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
@@ -1,5 +1,5 @@
1
1
  module ROM
2
2
  module HTTP
3
- VERSION = '0.1.0'.freeze
3
+ VERSION = '0.1.1'.freeze
4
4
  end
5
5
  end
@@ -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(1)
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(1).relation)
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(:dataset) { ROM::HTTP::Dataset.new(config, options) }
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 '#==' do
62
- subject { dataset == other }
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
- context 'with config and options equal' do
65
- let(:other) { ROM::HTTP::Dataset.new(dataset.config, dataset.options) }
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
- it { is_expected.to be true }
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 'with config and options equal' do
71
- let(:other) do
72
- ROM::HTTP::Dataset.new(dataset.config, dataset.options.merge(path: Random.new_seed))
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 { is_expected.to be false }
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
- it { expect(dataset.uri).to eq(uri) }
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
- before do
462
- allow(request_handler).to receive(:call).and_return(response)
463
- allow(response_handler).to receive(:call).and_return(result)
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
- subject! { dataset.response }
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
- it { expect(request_handler).to have_received(:call).with(dataset) }
469
- it { expect(response_handler).to have_received(:call).with(response, dataset) }
470
- it { is_expected.to eq(result) }
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 'required config' do
33
- it 'errors if config does not meet requirements' do
34
- expect { ROM::HTTP::Gateway.new({}) }.to raise_error(ROM::HTTP::GatewayConfigurationError)
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.0
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-08-19 00:00:00.000000000 Z
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