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 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