faraday-xml 0.2.0 → 0.2.2

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
  SHA256:
3
- metadata.gz: fd31db052ce943d7b8f60e8396449da83c134b70f3fe59f52e105edf1105f20d
4
- data.tar.gz: 80348c82aa221ff79dbb488bf11b7df6adecbb877887165899a6d057197bc12d
3
+ metadata.gz: bfc2270ae122bf4862391d61316eaa8fc955c54eab0a7252c05f810e3fdb9581
4
+ data.tar.gz: c5ef755fa5116a60e49b6ffcd95ef064d772e5cec6194caa6b781b5252a01cc5
5
5
  SHA512:
6
- metadata.gz: 33acfe362ff340f1e39f40a1610c77b98ccd89d7b0e107625fd2d7fc4ef08ed52c34166a3903cdb64514f5861a7420d181495355572d772be0b697870fb5986f
7
- data.tar.gz: 347b1ab466889029e44fb4cba75d5845bcf959544154d4fc8cb653a2988397f8a7edb19e4e7115d77594e83962ac07a017c0ab15f8fba76339fc3124b6676b23
6
+ metadata.gz: 6c820a24b3d85c926d00b05f4b9e004f202f8a0d40909d1591cd1b7de2e1c9b3f0db4c002b71e32dde03e298b51d8d8365dd45e49e308be2e08bac1985dd346f
7
+ data.tar.gz: 5652443216ed9d011e8115832ac4f05dd4b514483ddd0d3dfcd0fd0eb9f34f2cc063977306c17712f7610f1c68fce4265dcb0061c8246c26788c715ff22d9c43
data/CHANGELOG.md CHANGED
@@ -1,11 +1,22 @@
1
1
  # Changelog
2
2
 
3
- ## [Unreleased](https://github.com/gemhome/faraday-xml/compare/v0.2.0...main)
3
+ ## [Unreleased](https://github.com/gemhome/faraday-xml/compare/v0.3.0...main)
4
+
5
+ ## [0.2.2](https://github.com/gemhome/faraday-xml/compare/v0.2.1...v0.2.2) (2026-02-12)
6
+
7
+ - feat: Add support for Ruby 4.0
8
+ - chore: Update development dependencies to latest versions
9
+ - chore: Update CI matrix to test Ruby 3.2, 3.3, 3.4, and 4.0
10
+
11
+ ## [0.2.1](https://github.com/gemhome/faraday-xml/compare/v0.2.0...v0.2.1)
12
+
13
+ - feat: extract Faraday::XML::Encoder
14
+ - feat: extract Faraday::XML::Parser
4
15
 
5
16
  ## [0.2.0](https://github.com/gemhome/faraday-xml/compare/v0.1.0...v0.2.0)
6
17
 
7
- * feat: simple Hash -> XML request encoder
18
+ - feat: simple Hash -> XML request encoder
8
19
 
9
20
  ## [0.1.0](https://github.com/gemhome/faraday-xml/blob/v0.1.0) (2023-01-12)
10
21
 
11
- * feat: Initial release.
22
+ - feat: Initial release.
data/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # Faraday XML
2
2
 
3
- [![GitHub Workflow Status](https://img.shields.io/github/workflow/status/gemhome/faraday-xml/ci)](https://github.com/gemhome/faraday-xml/actions?query=branch%3Amain)
3
+ [![CI](https://github.com/gemhome/faraday-xml/actions/workflows/ci.yaml/badge.svg)](https://github.com/gemhome/faraday-xml/actions/workflows/ci.yaml)
4
4
  [![Gem](https://img.shields.io/gem/v/faraday-xml.svg?style=flat-square)](https://rubygems.org/gems/faraday-xml)
5
5
  [![License](https://img.shields.io/github/license/gemhome/faraday-xml.svg?style=flat-square)](LICENSE.md)
6
6
 
@@ -44,6 +44,21 @@ conn = Faraday.new do |builder|
44
44
  end
45
45
  ```
46
46
 
47
+ There is also basic support for first class XML encoding/parsing
48
+
49
+ ```ruby
50
+ require 'faraday'
51
+ require 'faraday/xml'
52
+ hash = { 'user' => { 'name' => 'Erik Michaels-Ober', 'screen_name' => 'sferik' } }
53
+ xml = '<user><name>Erik Michaels-Ober</name><screen_name>sferik</screen_name></user>'
54
+
55
+ encoder = Faraday::XML::Encoder.build!(indent: 0)
56
+ encoder.encode(hash) == xml
57
+
58
+ parser = Faraday::XML::Parser.build!
59
+ parser.parse(xml) == hash
60
+ ```
61
+
47
62
  ## Development
48
63
 
49
64
  After checking out the repo, run `bin/setup` to install dependencies.
@@ -0,0 +1,104 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Faraday
4
+ module XML
5
+ # Utility fucntion that encodes input as XML.
6
+ #
7
+ # Doesn't try to encode input which already are in string form.
8
+ class Encoder
9
+ def self.build!(encoder_options = {})
10
+ encoder = new(encoder_options)
11
+ encoder.encoder!
12
+ encoder
13
+ end
14
+
15
+ def initialize(encoder_options = {})
16
+ @encoder_options = encoder_options || {}
17
+ end
18
+
19
+ def encode(data)
20
+ encoder.call(data)
21
+ end
22
+
23
+ def encoder
24
+ @encoder ||= nil
25
+ if @encoder.nil?
26
+ @encoder = set_encoder
27
+ @encoder && test_encoder
28
+ end
29
+ @encoder or raise 'Missing dependencies Builder'
30
+ end
31
+ alias encoder! encoder
32
+
33
+ def test_encoder
34
+ encode({ success: true })
35
+ end
36
+
37
+ def set_encoder
38
+ @encoder ||= # rubocop:disable Naming/MemoizedInstanceVariableName
39
+ begin
40
+ require 'builder'
41
+ lambda do |parameter_hash|
42
+ parameters_as_xml(parameter_hash)
43
+ end
44
+ rescue LoadError # rubocop:disable Lint/SuppressedException
45
+ end
46
+ end
47
+
48
+ def parameters_as_xml(parameter_hash) # rubocop:disable Metrics/MethodLength
49
+ xml_markup = build_xml_markup(skip_instruct: true)
50
+ parameter_hash.each_pair do |key, value|
51
+ key = key.to_s
52
+ if _parameter_as_xml?(value)
53
+ xml_markup.tag!(key) do
54
+ xml = _parameter_as_xml(value)
55
+ xml_markup << xml
56
+ end
57
+ else
58
+ xml_markup.tag!(key, _parameter_as_xml(value))
59
+ end
60
+ end
61
+ xml_markup.target!
62
+ end
63
+
64
+ def _parameter_as_xml?(value)
65
+ case value
66
+ when Hash, Array then true
67
+ else false
68
+ end
69
+ end
70
+
71
+ def _parameter_as_xml(value)
72
+ case value
73
+ when Hash
74
+ parameters_as_xml(value) # recursive case
75
+ when Array
76
+ _parameter_as_list_xml(value) # recursive case
77
+ else
78
+ value.to_s.encode(xml: :text) # end case
79
+ end
80
+ end
81
+
82
+ def _parameter_as_list_xml(array_of_hashes)
83
+ xml_markup = build_xml_markup(skip_instruct: true)
84
+ array_of_hashes.each do |value|
85
+ xml_markup << parameters_as_xml(value) # recursive case
86
+ end
87
+ xml_markup.target!
88
+ end
89
+
90
+ def build_xml_markup(**options)
91
+ # https://github.com/rails/rails/blob/86fd8d0143b1a0578b359f4b86fea94c718139ae/activesupport/lib/active_support/builder.rb
92
+ # https://github.com/rails/rails/blob/86fd8d0143b1a0578b359f4b86fea94c718139ae/activesupport/lib/active_support/core_ext/hash/conversions.rb
93
+ require 'builder'
94
+ options.merge!(@encoder_options)
95
+ options[:indent] = 2 unless options.key?(:indent)
96
+ xml_markup = ::Builder::XmlMarkup.new(**options)
97
+ if !options.delete(:skip_instruct) # rubocop:disable Style/NegatedIf
98
+ xml_markup.instruct! :xml, version: '1.0', encoding: 'UTF-8'
99
+ end
100
+ xml_markup
101
+ end
102
+ end
103
+ end
104
+ end
@@ -0,0 +1,55 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Faraday
4
+ module XML
5
+ # Utility fucntion that parses XML input.
6
+ class Parser
7
+ def self.build!
8
+ parser = new
9
+ parser.parser!
10
+ parser
11
+ end
12
+
13
+ def parse(xml, parser_options = {})
14
+ parser.call(xml, parser_options)
15
+ end
16
+
17
+ def parser
18
+ @parser ||= nil
19
+ if @parser.nil?
20
+ @parser = set_parser
21
+ @parser && test_parser
22
+ end
23
+ @parser or raise 'Missing dependencies ActiveSupport::XmlMini or MultiXml'
24
+ end
25
+ alias parser! parser
26
+
27
+ def test_parser
28
+ parse('<success>true</success>')
29
+ end
30
+
31
+ def set_parser # rubocop:disable Metrics/MethodLength
32
+ @parser ||=
33
+ begin
34
+ require 'multi_xml'
35
+ lambda do |xml, options|
36
+ ::MultiXml.parse(xml, options)
37
+ end
38
+ rescue LoadError # rubocop:disable Lint/SuppressedException
39
+ end
40
+ @parser ||= # rubocop:disable Naming/MemoizedInstanceVariableName
41
+ begin
42
+ require 'active_support'
43
+ require 'active_support/xml_mini'
44
+ require 'active_support/core_ext/hash/conversions'
45
+ require 'active_support/core_ext/array/conversions'
46
+ lambda do |xml, options|
47
+ disallowed_types = options[:disallowed_types]
48
+ Hash.from_xml(xml, disallowed_types)
49
+ end
50
+ rescue LoadError # rubocop:disable Lint/SuppressedException
51
+ end
52
+ end
53
+ end
54
+ end
55
+ end
@@ -1,5 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require_relative 'encoder'
4
+
3
5
  module Faraday
4
6
  module XML
5
7
  # Request middleware that encodes the body as XML.
@@ -9,9 +11,9 @@ module Faraday
9
11
  # to XML MIME-type.
10
12
  #
11
13
  # Doesn't try to encode bodies that already are in string form.
12
- class Request < Middleware # rubocop:disable Metrics/ClassLength
14
+ class Request < Middleware
13
15
  MIME_TYPE = 'application/xml'
14
- MIME_TYPE_REGEX = %r{^application/(vnd\..+\+)?xml$}.freeze
16
+ MIME_TYPE_REGEX = %r{^application/(vnd\..+\+)?xml$}
15
17
 
16
18
  def initialize(app = nil, options = {})
17
19
  super(app)
@@ -20,40 +22,16 @@ module Faraday
20
22
 
21
23
  def on_request(env)
22
24
  match_content_type(env) do |data|
23
- env[:body] = encode(data)
25
+ env[:body] = encoder.encode(data)
24
26
  end
25
27
  end
26
28
 
27
29
  def encoder
28
- @encoder ||= nil
29
- if @encoder.nil?
30
- @encoder = set_encoder
31
- @encoder && test_encoder
32
- end
33
- @encoder or raise 'Missing dependencies Builder'
30
+ @encoder ||= Encoder.build!(@encoder_options)
34
31
  end
35
32
 
36
33
  private
37
34
 
38
- def encode(data)
39
- encoder.call(data)
40
- end
41
-
42
- def test_encoder
43
- encode({ success: true })
44
- end
45
-
46
- def set_encoder
47
- @encoder ||= # rubocop:disable Naming/MemoizedInstanceVariableName
48
- begin
49
- require 'builder'
50
- lambda do |parameter_hash|
51
- parameters_as_xml(parameter_hash)
52
- end
53
- rescue LoadError # rubocop:disable Lint/SuppressedException
54
- end
55
- end
56
-
57
35
  def match_content_type(env)
58
36
  return unless process_request?(env)
59
37
 
@@ -75,61 +53,6 @@ module Faraday
75
53
  type = type.split(';', 2).first if type.index(';')
76
54
  type
77
55
  end
78
-
79
- def parameters_as_xml(parameter_hash) # rubocop:disable Metrics/MethodLength
80
- xml_markup = build_xml_markup(skip_instruct: true)
81
- parameter_hash.each_pair do |key, value|
82
- key = key.to_s
83
- if _parameter_as_xml?(value)
84
- xml_markup.tag!(key) do
85
- xml = _parameter_as_xml(value)
86
- xml_markup << xml
87
- end
88
- else
89
- xml_markup.tag!(key, _parameter_as_xml(value))
90
- end
91
- end
92
- xml_markup.target!
93
- end
94
-
95
- def _parameter_as_xml?(value)
96
- case value
97
- when Hash, Array then true
98
- else false
99
- end
100
- end
101
-
102
- def _parameter_as_xml(value)
103
- case value
104
- when Hash
105
- parameters_as_xml(value) # recursive case
106
- when Array
107
- _parameter_as_list_xml(value) # recursive case
108
- else
109
- value.to_s.encode(xml: :text) # end case
110
- end
111
- end
112
-
113
- def _parameter_as_list_xml(array_of_hashes)
114
- xml_markup = build_xml_markup(skip_instruct: true)
115
- array_of_hashes.each do |value|
116
- xml_markup << parameters_as_xml(value) # recursive case
117
- end
118
- xml_markup.target!
119
- end
120
-
121
- def build_xml_markup(**options)
122
- # https://github.com/rails/rails/blob/86fd8d0143b1a0578b359f4b86fea94c718139ae/activesupport/lib/active_support/builder.rb
123
- # https://github.com/rails/rails/blob/86fd8d0143b1a0578b359f4b86fea94c718139ae/activesupport/lib/active_support/core_ext/hash/conversions.rb
124
- require 'builder'
125
- options.merge!(@encoder_options)
126
- options[:indent] = 2 unless options.key?(:indent)
127
- xml_markup = ::Builder::XmlMarkup.new(**options)
128
- if !options.delete(:skip_instruct) # rubocop:disable Style/NegatedIf
129
- xml_markup.instruct! :xml, version: '1.0', encoding: 'UTF-8'
130
- end
131
- xml_markup
132
- end
133
56
  end
134
57
  end
135
58
  end
@@ -1,5 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require_relative 'parser'
4
+
3
5
  module Faraday
4
6
  module XML
5
7
  # Parse response bodies as XML
@@ -17,12 +19,7 @@ module Faraday
17
19
  end
18
20
 
19
21
  def parser
20
- @parser ||= nil
21
- if @parser.nil?
22
- @parser = set_parser
23
- @parser && test_parser
24
- end
25
- @parser or raise 'Missing dependencies ActiveSupport::XmlMini or MultiXml'
22
+ @parser ||= Parser.build!
26
23
  end
27
24
 
28
25
  private
@@ -37,34 +34,7 @@ module Faraday
37
34
  def parse(body)
38
35
  return nil if body.strip.empty?
39
36
 
40
- parser.call(body, @parser_options || {})
41
- end
42
-
43
- def test_parser
44
- parse('<success>true</success>')
45
- end
46
-
47
- def set_parser # rubocop:disable Metrics/MethodLength
48
- @parser ||=
49
- begin
50
- require 'multi_xml'
51
- lambda do |xml, options|
52
- ::MultiXml.parse(xml, options)
53
- end
54
- rescue LoadError # rubocop:disable Lint/SuppressedException
55
- end
56
- @parser ||= # rubocop:disable Naming/MemoizedInstanceVariableName
57
- begin
58
- require 'active_support'
59
- require 'active_support/xml_mini'
60
- require 'active_support/core_ext/hash/conversions'
61
- require 'active_support/core_ext/array/conversions'
62
- lambda do |xml, options|
63
- disallowed_types = options[:disallowed_types]
64
- Hash.from_xml(xml, disallowed_types)
65
- end
66
- rescue LoadError # rubocop:disable Lint/SuppressedException
67
- end
37
+ parser.parse(body, @parser_options || {})
68
38
  end
69
39
 
70
40
  def parse_response?(env)
@@ -2,6 +2,6 @@
2
2
 
3
3
  module Faraday
4
4
  module XML
5
- VERSION = '0.2.0'
5
+ VERSION = '0.2.2'
6
6
  end
7
7
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: faraday-xml
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.0
4
+ version: 0.2.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Benjamin Fleischer
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2023-01-23 00:00:00.000000000 Z
11
+ date: 2026-02-13 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: faraday
@@ -30,20 +30,6 @@ dependencies:
30
30
  - - "<"
31
31
  - !ruby/object:Gem::Version
32
32
  version: '3'
33
- - !ruby/object:Gem::Dependency
34
- name: bundler
35
- requirement: !ruby/object:Gem::Requirement
36
- requirements:
37
- - - "~>"
38
- - !ruby/object:Gem::Version
39
- version: '2.0'
40
- type: :development
41
- prerelease: false
42
- version_requirements: !ruby/object:Gem::Requirement
43
- requirements:
44
- - - "~>"
45
- - !ruby/object:Gem::Version
46
- version: '2.0'
47
33
  - !ruby/object:Gem::Dependency
48
34
  name: rake
49
35
  requirement: !ruby/object:Gem::Requirement
@@ -64,84 +50,28 @@ dependencies:
64
50
  requirements:
65
51
  - - "~>"
66
52
  - !ruby/object:Gem::Version
67
- version: '3.0'
53
+ version: '3.13'
68
54
  type: :development
69
55
  prerelease: false
70
56
  version_requirements: !ruby/object:Gem::Requirement
71
57
  requirements:
72
58
  - - "~>"
73
59
  - !ruby/object:Gem::Version
74
- version: '3.0'
60
+ version: '3.13'
75
61
  - !ruby/object:Gem::Dependency
76
62
  name: simplecov
77
63
  requirement: !ruby/object:Gem::Requirement
78
64
  requirements:
79
65
  - - "~>"
80
66
  - !ruby/object:Gem::Version
81
- version: 0.21.0
82
- type: :development
83
- prerelease: false
84
- version_requirements: !ruby/object:Gem::Requirement
85
- requirements:
86
- - - "~>"
87
- - !ruby/object:Gem::Version
88
- version: 0.21.0
89
- - !ruby/object:Gem::Dependency
90
- name: rubocop
91
- requirement: !ruby/object:Gem::Requirement
92
- requirements:
93
- - - "~>"
94
- - !ruby/object:Gem::Version
95
- version: 1.31.0
96
- type: :development
97
- prerelease: false
98
- version_requirements: !ruby/object:Gem::Requirement
99
- requirements:
100
- - - "~>"
101
- - !ruby/object:Gem::Version
102
- version: 1.31.0
103
- - !ruby/object:Gem::Dependency
104
- name: rubocop-packaging
105
- requirement: !ruby/object:Gem::Requirement
106
- requirements:
107
- - - "~>"
108
- - !ruby/object:Gem::Version
109
- version: 0.5.0
110
- type: :development
111
- prerelease: false
112
- version_requirements: !ruby/object:Gem::Requirement
113
- requirements:
114
- - - "~>"
115
- - !ruby/object:Gem::Version
116
- version: 0.5.0
117
- - !ruby/object:Gem::Dependency
118
- name: rubocop-performance
119
- requirement: !ruby/object:Gem::Requirement
120
- requirements:
121
- - - "~>"
122
- - !ruby/object:Gem::Version
123
- version: '1.0'
124
- type: :development
125
- prerelease: false
126
- version_requirements: !ruby/object:Gem::Requirement
127
- requirements:
128
- - - "~>"
129
- - !ruby/object:Gem::Version
130
- version: '1.0'
131
- - !ruby/object:Gem::Dependency
132
- name: rubocop-rspec
133
- requirement: !ruby/object:Gem::Requirement
134
- requirements:
135
- - - "~>"
136
- - !ruby/object:Gem::Version
137
- version: '2.0'
67
+ version: 0.22.0
138
68
  type: :development
139
69
  prerelease: false
140
70
  version_requirements: !ruby/object:Gem::Requirement
141
71
  requirements:
142
72
  - - "~>"
143
73
  - !ruby/object:Gem::Version
144
- version: '2.0'
74
+ version: 0.22.0
145
75
  description: 'Faraday XML Middleware.
146
76
 
147
77
  '
@@ -155,6 +85,8 @@ files:
155
85
  - LICENSE.md
156
86
  - README.md
157
87
  - lib/faraday/xml.rb
88
+ - lib/faraday/xml/encoder.rb
89
+ - lib/faraday/xml/parser.rb
158
90
  - lib/faraday/xml/request.rb
159
91
  - lib/faraday/xml/response.rb
160
92
  - lib/faraday/xml/version.rb
@@ -163,8 +95,8 @@ licenses:
163
95
  - MIT
164
96
  metadata:
165
97
  bug_tracker_uri: https://github.com/gemhome/faraday-xml/issues
166
- changelog_uri: https://github.com/gemhome/faraday-xml/blob/v0.2.0/CHANGELOG.md
167
- documentation_uri: http://www.rubydoc.info/gems/faraday-xml/0.2.0
98
+ changelog_uri: https://github.com/gemhome/faraday-xml/blob/v0.2.2/CHANGELOG.md
99
+ documentation_uri: http://www.rubydoc.info/gems/faraday-xml/0.2.2
168
100
  homepage_uri: https://github.com/gemhome/faraday-xml
169
101
  rubygems_mfa_required: 'true'
170
102
  source_code_uri: https://github.com/gemhome/faraday-xml
@@ -178,9 +110,6 @@ required_ruby_version: !ruby/object:Gem::Requirement
178
110
  - - ">="
179
111
  - !ruby/object:Gem::Version
180
112
  version: '2.6'
181
- - - "<"
182
- - !ruby/object:Gem::Version
183
- version: '4'
184
113
  required_rubygems_version: !ruby/object:Gem::Requirement
185
114
  requirements:
186
115
  - - ">="