rom-http 0.7.0 → 0.8.0

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.
Files changed (46) hide show
  1. checksums.yaml +5 -5
  2. data/CHANGELOG.md +26 -2
  3. data/LICENSE.txt +1 -1
  4. data/README.md +12 -15
  5. data/lib/rom-http.rb +2 -0
  6. data/lib/rom/http.rb +2 -0
  7. data/lib/rom/http/attribute.rb +10 -0
  8. data/lib/rom/http/commands.rb +2 -0
  9. data/lib/rom/http/commands/create.rb +2 -0
  10. data/lib/rom/http/commands/delete.rb +2 -0
  11. data/lib/rom/http/commands/update.rb +2 -0
  12. data/lib/rom/http/dataset.rb +152 -101
  13. data/lib/rom/http/error.rb +2 -0
  14. data/lib/rom/http/gateway.rb +44 -3
  15. data/lib/rom/http/handlers.rb +14 -0
  16. data/lib/rom/http/handlers/json.rb +65 -0
  17. data/lib/rom/http/mapper_compiler.rb +11 -0
  18. data/lib/rom/http/relation.rb +19 -64
  19. data/lib/rom/http/schema.rb +20 -0
  20. data/lib/rom/http/schema/dsl.rb +12 -0
  21. data/lib/rom/http/transformer.rb +2 -0
  22. data/lib/rom/http/types.rb +13 -0
  23. data/lib/rom/http/version.rb +3 -1
  24. metadata +32 -59
  25. data/.gitignore +0 -16
  26. data/.rspec +0 -3
  27. data/.rubocop.yml +0 -22
  28. data/.rubocop_todo.yml +0 -12
  29. data/.travis.yml +0 -20
  30. data/Gemfile +0 -24
  31. data/Rakefile +0 -24
  32. data/examples/repository_with_combine.rb +0 -154
  33. data/lib/rom/http/dataset/class_interface.rb +0 -33
  34. data/rakelib/rubocop.rake +0 -18
  35. data/rom-http.gemspec +0 -32
  36. data/spec/integration/abstract/commands/create_spec.rb +0 -119
  37. data/spec/integration/abstract/commands/delete_spec.rb +0 -52
  38. data/spec/integration/abstract/commands/update_spec.rb +0 -119
  39. data/spec/integration/abstract/relation_spec.rb +0 -78
  40. data/spec/shared/setup.rb +0 -18
  41. data/spec/shared/users_and_tasks.rb +0 -30
  42. data/spec/spec_helper.rb +0 -19
  43. data/spec/support/mutant.rb +0 -10
  44. data/spec/unit/rom/http/dataset_spec.rb +0 -824
  45. data/spec/unit/rom/http/gateway_spec.rb +0 -69
  46. data/spec/unit/rom/http/relation_spec.rb +0 -268
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module ROM
2
4
  module HTTP
3
5
  Error = Class.new(StandardError)
@@ -1,5 +1,10 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'concurrent'
4
+
2
5
  require 'rom/http/dataset'
6
+ require 'rom/http/handlers'
7
+ require 'rom/http/mapper_compiler'
3
8
 
4
9
  module ROM
5
10
  module HTTP
@@ -19,7 +24,6 @@ module ROM
19
24
  adapter :http
20
25
 
21
26
  attr_reader :datasets, :config
22
- private :datasets, :config
23
27
 
24
28
  # HTTP gateway interface
25
29
  #
@@ -54,8 +58,7 @@ module ROM
54
58
  #
55
59
  # @api public
56
60
  def dataset(name)
57
- dataset_klass = namespace.const_defined?(:Dataset) ? namespace.const_get(:Dataset) : Dataset
58
- datasets[name] = dataset_klass.new(config.merge(name: name))
61
+ datasets[name] = dataset_class.new(dataset_options(name))
59
62
  end
60
63
 
61
64
  # Check if dataset exists
@@ -69,6 +72,44 @@ module ROM
69
72
 
70
73
  private
71
74
 
75
+ # Return Dataset class
76
+ #
77
+ # @return [Class]
78
+ #
79
+ # @api private
80
+ def dataset_class
81
+ namespace.const_defined?(:Dataset) ? namespace.const_get(:Dataset) : Dataset
82
+ end
83
+
84
+ # Return Dataset options
85
+ #
86
+ # @return [Class]
87
+ #
88
+ # @api private
89
+ def dataset_options(name)
90
+ config.merge(uri: uri, base_path: name, **default_handlers)
91
+ end
92
+
93
+ # Return default handlers registered in Handlers registry
94
+ #
95
+ # @return [Hash]
96
+ #
97
+ # @api private
98
+ def default_handlers
99
+ if handlers_key = config[:handlers]
100
+ Handlers[handlers_key]
101
+ .map { |key, value| [:"#{key}_handler", value] }.to_h
102
+ else
103
+ EMPTY_HASH
104
+ end
105
+ end
106
+
107
+ # @api private
108
+ def uri
109
+ config.fetch(:uri) { fail Error, '+uri+ configuration missing' }
110
+ end
111
+
112
+ # @api private
72
113
  def namespace
73
114
  self.class.to_s[/(.*)(?=::)/].split('::').inject(::Object) do |constant, const_name|
74
115
  constant.const_get(const_name)
@@ -0,0 +1,14 @@
1
+ require 'rom/http/handlers/json'
2
+
3
+ module ROM
4
+ module HTTP
5
+ # Request/response handler registry
6
+ #
7
+ # @api public
8
+ class Handlers
9
+ extend Dry::Container::Mixin
10
+
11
+ register(:json, request: JSONRequest, response: JSONResponse)
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,65 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'uri'
4
+ require 'net/http'
5
+ require 'json'
6
+
7
+ require 'rom/support/inflector'
8
+
9
+ module ROM
10
+ module HTTP
11
+ # Default request/response handlers
12
+ #
13
+ # @api public
14
+ class Handlers
15
+ # Default handler for JSON requests
16
+ #
17
+ # @api public
18
+ class JSONRequest
19
+ # Handle JSON request for the provided dataset
20
+ #
21
+ # @param [Dataset] dataset
22
+ #
23
+ # @return [Array<Hash>]
24
+ #
25
+ # @api public
26
+ def self.call(dataset)
27
+ uri = URI(dataset.uri)
28
+
29
+ uri.path = dataset.absolute_path
30
+ uri.query = URI.encode_www_form(dataset.params)
31
+
32
+ http = Net::HTTP.new(uri.host, uri.port)
33
+ http.use_ssl = true if uri.scheme.eql?('https')
34
+
35
+ request_class = Net::HTTP.const_get(ROM::Inflector.classify(dataset.request_method))
36
+
37
+ request = request_class.new(uri.request_uri)
38
+
39
+ dataset.headers.each_with_object(request) do |(header, value), request|
40
+ request[header.to_s] = value
41
+ end
42
+
43
+ http.request(request)
44
+ end
45
+ end
46
+
47
+ # Default handler for JSON responses
48
+ #
49
+ # @api public
50
+ class JSONResponse
51
+ # Handle JSON responses
52
+ #
53
+ # @param [Net::HTTP::Response] response
54
+ # @param [Dataset] dataset
55
+ #
56
+ # @return [Array<Hash>]
57
+ #
58
+ # @api public
59
+ def self.call(response, dataset)
60
+ Array([JSON.parse(response.body)]).flatten(1)
61
+ end
62
+ end
63
+ end
64
+ end
65
+ end
@@ -0,0 +1,11 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'rom/mapper_compiler'
4
+
5
+ module ROM
6
+ module HTTP
7
+ class MapperCompiler < ROM::MapperCompiler
8
+ mapper_options(reject_keys: true)
9
+ end
10
+ end
11
+ end
@@ -1,32 +1,33 @@
1
- require 'dry/core/cache'
1
+ # frozen_string_literal: true
2
+
2
3
  require 'rom/initializer'
3
- require 'rom/http/transformer'
4
+
5
+ require 'rom/http/types'
6
+ require 'rom/http/attribute'
7
+ require 'rom/http/schema'
8
+ require 'rom/http/schema/dsl'
4
9
 
5
10
  module ROM
6
11
  module HTTP
7
12
  # HTTP-specific relation extensions
8
13
  #
9
14
  class Relation < ROM::Relation
10
- extend Dry::Core::Cache
11
- extend ::ROM::Initializer
12
- include Enumerable
15
+ include ROM::HTTP
13
16
 
14
17
  adapter :http
15
18
 
16
- option :transformer, reader: true, default: proc { ::ROM::HTTP::Transformer }
19
+ schema_class HTTP::Schema
20
+ schema_dsl HTTP::Schema::DSL
21
+ schema_attr_class HTTP::Attribute
22
+
23
+ option :output_schema, default: -> { schema.to_output_hash }
17
24
 
18
25
  forward :with_headers, :add_header, :with_options,
19
26
  :with_base_path, :with_path, :append_path,
20
27
  :with_request_method, :with_params, :add_params
21
28
 
22
29
  def primary_key
23
- attribute = schema.find(&:primary_key?)
24
-
25
- if attribute
26
- attribute.alias || attribute.name
27
- else
28
- :id
29
- end
30
+ schema.primary_key_name
30
31
  end
31
32
 
32
33
  def project(*names)
@@ -34,7 +35,7 @@ module ROM
34
35
  end
35
36
 
36
37
  def exclude(*names)
37
- with(schema: schema.exclude(*names.flatten))
38
+ with(schema: schema.exclude(*names))
38
39
  end
39
40
 
40
41
  def rename(mapping)
@@ -45,67 +46,21 @@ module ROM
45
46
  with(schema: schema.prefix(prefix))
46
47
  end
47
48
 
48
- def wrap(prefix = dataset.name)
49
- with(schema: schema.wrap(prefix))
50
- end
51
-
52
- def to_a
53
- with_transformation { super }
54
- end
55
-
56
49
  # @see Dataset#insert
57
- def insert(*args)
58
- with_transformation { dataset.insert(*args) }
50
+ def insert(*tuples)
51
+ dataset.insert(*tuples.map { |t| input_schema[t] })
59
52
  end
60
53
  alias_method :<<, :insert
61
54
 
62
55
  # @see Dataset#update
63
- def update(*args)
64
- with_transformation { dataset.update(*args) }
56
+ def update(*tuples)
57
+ dataset.update(*tuples.map { |t| input_schema[t] })
65
58
  end
66
59
 
67
60
  # @see Dataset#delete
68
61
  def delete
69
62
  dataset.delete
70
63
  end
71
-
72
- private
73
-
74
- def with_transformation
75
- tuples = yield
76
-
77
- transformed = with_schema_proc do |proc|
78
- transformer_proc[Array([tuples]).flatten(1).map(&proc.method(:call))]
79
- end
80
-
81
- tuples.kind_of?(Array) ? transformed : transformed.first
82
- end
83
-
84
- def with_schema_proc
85
- schema_proc = fetch_or_store(schema) do
86
- Types::Coercible::Hash.schema(schema.to_h)
87
- end
88
-
89
- yield(schema_proc)
90
- end
91
-
92
- def transformer_proc
93
- if mapped?
94
- transformer[:map_array, transformer[:rename_keys, mapping]]
95
- else
96
- transformer[:identity]
97
- end
98
- end
99
-
100
- def mapped?
101
- mapping.any?
102
- end
103
-
104
- def mapping
105
- schema.each_with_object({}) do |attr, mapping|
106
- mapping[attr.name] = attr.alias if attr.alias
107
- end
108
- end
109
64
  end
110
65
  end
111
66
  end
@@ -0,0 +1,20 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'rom/schema'
4
+ require 'rom/http/types'
5
+
6
+ module ROM
7
+ module HTTP
8
+ class Schema < ROM::Schema
9
+ # Customized output hash constructor which symbolizes keys
10
+ # and optionally applies custom read-type coercions
11
+ #
12
+ # @api private
13
+ def to_output_hash
14
+ Types::Hash
15
+ .schema(map { |attr| [attr.key, attr.to_read_type] }.to_h)
16
+ .with_key_transform(&:to_sym)
17
+ end
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,12 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'rom/schema/dsl'
4
+
5
+ module ROM
6
+ module HTTP
7
+ class Schema < ROM::Schema
8
+ class DSL < ROM::Schema::DSL
9
+ end
10
+ end
11
+ end
12
+ end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module ROM
2
4
  module HTTP
3
5
  # Transformer
@@ -0,0 +1,13 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'rom/types'
4
+
5
+ module ROM
6
+ module HTTP
7
+ module Types
8
+ include ROM::Types
9
+
10
+ Path = Coercible::String.constructor { |s| s.sub(%r{\A/}, '') }
11
+ end
12
+ end
13
+ end
@@ -1,5 +1,7 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module ROM
2
4
  module HTTP
3
- VERSION = '0.7.0'.freeze
5
+ VERSION = '0.8.0'.freeze
4
6
  end
5
7
  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.7.0
4
+ version: 0.8.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Piotr Solnica
@@ -10,70 +10,70 @@ authors:
10
10
  autorequire:
11
11
  bindir: bin
12
12
  cert_chain: []
13
- date: 2018-01-11 00:00:00.000000000 Z
13
+ date: 2019-04-29 00:00:00.000000000 Z
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
16
  name: concurrent-ruby
17
17
  requirement: !ruby/object:Gem::Requirement
18
18
  requirements:
19
- - - ">="
19
+ - - "~>"
20
20
  - !ruby/object:Gem::Version
21
- version: '0'
21
+ version: '1.1'
22
22
  type: :runtime
23
23
  prerelease: false
24
24
  version_requirements: !ruby/object:Gem::Requirement
25
25
  requirements:
26
- - - ">="
26
+ - - "~>"
27
27
  - !ruby/object:Gem::Version
28
- version: '0'
28
+ version: '1.1'
29
29
  - !ruby/object:Gem::Dependency
30
30
  name: addressable
31
31
  requirement: !ruby/object:Gem::Requirement
32
32
  requirements:
33
- - - ">="
33
+ - - "~>"
34
34
  - !ruby/object:Gem::Version
35
- version: '0'
35
+ version: '2.6'
36
36
  type: :runtime
37
37
  prerelease: false
38
38
  version_requirements: !ruby/object:Gem::Requirement
39
39
  requirements:
40
- - - ">="
40
+ - - "~>"
41
41
  - !ruby/object:Gem::Version
42
- version: '0'
42
+ version: '2.6'
43
43
  - !ruby/object:Gem::Dependency
44
- name: rom
44
+ name: rom-core
45
45
  requirement: !ruby/object:Gem::Requirement
46
46
  requirements:
47
47
  - - "~>"
48
48
  - !ruby/object:Gem::Version
49
- version: '4.0'
49
+ version: '5.0'
50
+ - - ">="
51
+ - !ruby/object:Gem::Version
52
+ version: 5.0.1
50
53
  type: :runtime
51
54
  prerelease: false
52
55
  version_requirements: !ruby/object:Gem::Requirement
53
56
  requirements:
54
57
  - - "~>"
55
58
  - !ruby/object:Gem::Version
56
- version: '4.0'
59
+ version: '5.0'
60
+ - - ">="
61
+ - !ruby/object:Gem::Version
62
+ version: 5.0.1
57
63
  - !ruby/object:Gem::Dependency
58
64
  name: dry-core
59
65
  requirement: !ruby/object:Gem::Requirement
60
66
  requirements:
61
67
  - - "~>"
62
68
  - !ruby/object:Gem::Version
63
- version: '0.2'
64
- - - ">="
65
- - !ruby/object:Gem::Version
66
- version: 0.2.3
69
+ version: '0.4'
67
70
  type: :runtime
68
71
  prerelease: false
69
72
  version_requirements: !ruby/object:Gem::Requirement
70
73
  requirements:
71
74
  - - "~>"
72
75
  - !ruby/object:Gem::Version
73
- version: '0.2'
74
- - - ">="
75
- - !ruby/object:Gem::Version
76
- version: 0.2.3
76
+ version: '0.4'
77
77
  - !ruby/object:Gem::Dependency
78
78
  name: dry-equalizer
79
79
  requirement: !ruby/object:Gem::Requirement
@@ -167,44 +167,29 @@ executables: []
167
167
  extensions: []
168
168
  extra_rdoc_files: []
169
169
  files:
170
- - ".gitignore"
171
- - ".rspec"
172
- - ".rubocop.yml"
173
- - ".rubocop_todo.yml"
174
- - ".travis.yml"
175
170
  - CHANGELOG.md
176
- - Gemfile
177
171
  - LICENSE.txt
178
172
  - README.md
179
- - Rakefile
180
- - examples/repository_with_combine.rb
181
173
  - lib/rom-http.rb
182
174
  - lib/rom/http.rb
175
+ - lib/rom/http/attribute.rb
183
176
  - lib/rom/http/commands.rb
184
177
  - lib/rom/http/commands/create.rb
185
178
  - lib/rom/http/commands/delete.rb
186
179
  - lib/rom/http/commands/update.rb
187
180
  - lib/rom/http/dataset.rb
188
- - lib/rom/http/dataset/class_interface.rb
189
181
  - lib/rom/http/error.rb
190
182
  - lib/rom/http/gateway.rb
183
+ - lib/rom/http/handlers.rb
184
+ - lib/rom/http/handlers/json.rb
185
+ - lib/rom/http/mapper_compiler.rb
191
186
  - lib/rom/http/relation.rb
187
+ - lib/rom/http/schema.rb
188
+ - lib/rom/http/schema/dsl.rb
192
189
  - lib/rom/http/transformer.rb
190
+ - lib/rom/http/types.rb
193
191
  - lib/rom/http/version.rb
194
- - rakelib/rubocop.rake
195
- - rom-http.gemspec
196
- - spec/integration/abstract/commands/create_spec.rb
197
- - spec/integration/abstract/commands/delete_spec.rb
198
- - spec/integration/abstract/commands/update_spec.rb
199
- - spec/integration/abstract/relation_spec.rb
200
- - spec/shared/setup.rb
201
- - spec/shared/users_and_tasks.rb
202
- - spec/spec_helper.rb
203
- - spec/support/mutant.rb
204
- - spec/unit/rom/http/dataset_spec.rb
205
- - spec/unit/rom/http/gateway_spec.rb
206
- - spec/unit/rom/http/relation_spec.rb
207
- homepage: http://rom-rb.org
192
+ homepage: https://rom-rb.org
208
193
  licenses:
209
194
  - MIT
210
195
  metadata: {}
@@ -216,27 +201,15 @@ required_ruby_version: !ruby/object:Gem::Requirement
216
201
  requirements:
217
202
  - - ">="
218
203
  - !ruby/object:Gem::Version
219
- version: '0'
204
+ version: 2.4.0
220
205
  required_rubygems_version: !ruby/object:Gem::Requirement
221
206
  requirements:
222
207
  - - ">="
223
208
  - !ruby/object:Gem::Version
224
209
  version: '0'
225
210
  requirements: []
226
- rubyforge_project:
227
- rubygems_version: 2.6.13
211
+ rubygems_version: 3.0.3
228
212
  signing_key:
229
213
  specification_version: 4
230
214
  summary: HTTP support for ROM
231
- test_files:
232
- - spec/integration/abstract/commands/create_spec.rb
233
- - spec/integration/abstract/commands/delete_spec.rb
234
- - spec/integration/abstract/commands/update_spec.rb
235
- - spec/integration/abstract/relation_spec.rb
236
- - spec/shared/setup.rb
237
- - spec/shared/users_and_tasks.rb
238
- - spec/spec_helper.rb
239
- - spec/support/mutant.rb
240
- - spec/unit/rom/http/dataset_spec.rb
241
- - spec/unit/rom/http/gateway_spec.rb
242
- - spec/unit/rom/http/relation_spec.rb
215
+ test_files: []