rom-http 0.7.0 → 0.8.0

Sign up to get free protection for your applications and to get access to all the features.
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: []