aitch 1.0.1 → 1.2.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -5
- data/.github/FUNDING.yml +3 -0
- data/.github/workflows/tests.yml +50 -0
- data/.rubocop.yml +26 -0
- data/Gemfile +2 -2
- data/README.md +54 -14
- data/Rakefile +5 -1
- data/aitch.gemspec +12 -7
- data/lib/aitch/configuration.rb +5 -0
- data/lib/aitch/dsl.rb +4 -3
- data/lib/aitch/engines/json.rb +15 -0
- data/lib/aitch/errors.rb +1 -0
- data/lib/aitch/ext/to_query.rb +6 -10
- data/lib/aitch/location.rb +4 -3
- data/lib/aitch/namespace.rb +38 -14
- data/lib/aitch/redirect.rb +1 -0
- data/lib/aitch/request.rb +40 -28
- data/lib/aitch/response/body.rb +1 -0
- data/lib/aitch/response/description.rb +3 -2
- data/lib/aitch/response/errors.rb +2 -1
- data/lib/aitch/response.rb +9 -5
- data/lib/aitch/response_parser/default_parser.rb +2 -1
- data/lib/aitch/response_parser/html_parser.rb +1 -0
- data/lib/aitch/response_parser/json_parser.rb +2 -1
- data/lib/aitch/response_parser/xml_parser.rb +1 -0
- data/lib/aitch/response_parser.rb +8 -5
- data/lib/aitch/uri.rb +5 -2
- data/lib/aitch/utils.rb +3 -1
- data/lib/aitch/version.rb +2 -1
- data/lib/aitch.rb +13 -13
- data/test/aitch/aitch_test.rb +1 -0
- data/test/aitch/configuration_test.rb +2 -1
- data/test/aitch/dsl_test.rb +1 -0
- data/test/aitch/execute_test.rb +1 -0
- data/test/aitch/namespace_test.rb +2 -1
- data/test/aitch/request/client_https_test.rb +1 -0
- data/test/aitch/request/follow_redirect_test.rb +4 -3
- data/test/aitch/request/json_request_test.rb +1 -0
- data/test/aitch/request/request_class_test.rb +3 -2
- data/test/aitch/request/status_code_validation_test.rb +3 -2
- data/test/aitch/request_test.rb +45 -8
- data/test/aitch/response/custom_response_parser_test.rb +1 -4
- data/test/aitch/response/default_response_parser_test.rb +14 -0
- data/test/aitch/response/errors_test.rb +1 -0
- data/test/aitch/response/html_response_test.rb +1 -0
- data/test/aitch/response/json_response_test.rb +2 -1
- data/test/aitch/response/raw_response_test.rb +1 -0
- data/test/aitch/response/status_3xx_test.rb +1 -0
- data/test/aitch/response/status_4xx_test.rb +1 -0
- data/test/aitch/response/status_5xx_test.rb +1 -0
- data/test/aitch/response/xml_response_test.rb +1 -0
- data/test/aitch/response_parser/html_parser_test.rb +1 -0
- data/test/aitch/response_parser/json_parser_test.rb +2 -1
- data/test/aitch/response_parser/xml_parser_test.rb +1 -1
- data/test/aitch/response_test.rb +1 -1
- data/test/aitch/to_query_test.rb +28 -0
- data/test/aitch/uri_test.rb +2 -1
- data/test/aitch/utils/symbolize_keys_test.rb +1 -0
- data/test/aitch/utils/underscore_test.rb +1 -0
- data/test/support/helpers.rb +5 -4
- data/test/test_helper.rb +3 -2
- metadata +77 -15
- data/.travis.yml +0 -23
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: a3f4cd3269e5b709f85e34148b2ed6aad4a9080f9903dc625d4840d8ffc2293a
|
4
|
+
data.tar.gz: d97a344ec31e5f6ba528f1d359b96aa2860ab51e1cdde507d5cbc0557e9a75a4
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: a11acc6e165677b372cd4c9a07b9fd33640611a056fb1c437917ffa1d89ab0520bcaf9943cd5e8f72a3f088942a8f7b9d968a59ec7207dc6a061f54364216aba
|
7
|
+
data.tar.gz: a0228f9d4719ee0fddd2932fece69c454062d40f4526612b41044168198f7ec91478267163e343a995ceb5f8bbcdc1d4d228d8edb73a9845b5aa0d08145581c9
|
data/.github/FUNDING.yml
ADDED
@@ -0,0 +1,50 @@
|
|
1
|
+
---
|
2
|
+
name: Tests
|
3
|
+
|
4
|
+
on:
|
5
|
+
pull_request:
|
6
|
+
branches:
|
7
|
+
- main
|
8
|
+
push:
|
9
|
+
branches:
|
10
|
+
- main
|
11
|
+
jobs:
|
12
|
+
build:
|
13
|
+
name: Tests with Ruby ${{ matrix.ruby }}
|
14
|
+
runs-on: "ubuntu-latest"
|
15
|
+
strategy:
|
16
|
+
fail-fast: false
|
17
|
+
matrix:
|
18
|
+
ruby: ["2.7.x", "2.6.x", "2.5.x", "3.0.x", "3.1.x"]
|
19
|
+
|
20
|
+
steps:
|
21
|
+
- uses: actions/checkout@v1
|
22
|
+
|
23
|
+
- uses: actions/cache@v2
|
24
|
+
with:
|
25
|
+
path: vendor/bundle
|
26
|
+
key: >
|
27
|
+
${{ runner.os }}-${{ matrix.ruby }}-gems-${{
|
28
|
+
hashFiles('aitch.gemspec') }}
|
29
|
+
restore-keys: >
|
30
|
+
${{ runner.os }}-${{ matrix.ruby }}-gems-${{
|
31
|
+
hashFiles('aitch.gemspec') }}
|
32
|
+
|
33
|
+
- name: Set up Ruby
|
34
|
+
uses: actions/setup-ruby@v1
|
35
|
+
with:
|
36
|
+
ruby-version: ${{ matrix.ruby }}
|
37
|
+
|
38
|
+
- name: Install gem dependencies
|
39
|
+
env:
|
40
|
+
RAILS_ENV: test
|
41
|
+
run: |
|
42
|
+
gem install bundler
|
43
|
+
bundle config path vendor/bundle
|
44
|
+
bundle update --jobs 4 --retry 3
|
45
|
+
|
46
|
+
- name: Run Tests
|
47
|
+
env:
|
48
|
+
RAILS_ENV: test
|
49
|
+
run: |
|
50
|
+
bundle exec rake
|
data/.rubocop.yml
ADDED
@@ -0,0 +1,26 @@
|
|
1
|
+
---
|
2
|
+
inherit_gem:
|
3
|
+
rubocop-fnando: .rubocop.yml
|
4
|
+
|
5
|
+
AllCops:
|
6
|
+
TargetRubyVersion: 2.5
|
7
|
+
|
8
|
+
Layout/LineLength:
|
9
|
+
Exclude:
|
10
|
+
- test/**/*.rb
|
11
|
+
|
12
|
+
Naming/AccessorMethodName:
|
13
|
+
Exclude:
|
14
|
+
- lib/aitch/request.rb
|
15
|
+
|
16
|
+
Metrics/ClassLength:
|
17
|
+
Enabled: false
|
18
|
+
|
19
|
+
Metrics/AbcSize:
|
20
|
+
Enabled: false
|
21
|
+
|
22
|
+
Metrics/MethodLength:
|
23
|
+
Enabled: false
|
24
|
+
|
25
|
+
Metrics/ParameterLists:
|
26
|
+
Enabled: false
|
data/Gemfile
CHANGED
data/README.md
CHANGED
@@ -1,24 +1,24 @@
|
|
1
1
|
# Aitch
|
2
2
|
|
3
|
-
[![
|
3
|
+
[![Tests](https://github.com/fnando/aitch/workflows/Tests/badge.svg)](https://github.com/fnando/aitch)
|
4
4
|
[![Code Climate](https://codeclimate.com/github/fnando/aitch/badges/gpa.svg)](https://codeclimate.com/github/fnando/aitch)
|
5
|
-
[![
|
6
|
-
[![
|
5
|
+
[![Gem Version](https://img.shields.io/gem/v/aitch.svg)](https://rubygems.org/gems/aitch)
|
6
|
+
[![Gem Downloads](https://img.shields.io/gem/dt/aitch.svg)](https://rubygems.org/gems/aitch)
|
7
7
|
|
8
8
|
A simple HTTP client.
|
9
9
|
|
10
10
|
Features:
|
11
11
|
|
12
|
-
|
13
|
-
|
14
|
-
|
12
|
+
- Supports Gzip|Deflate response
|
13
|
+
- Automatically parses JSON, HTML and XML responses
|
14
|
+
- Automatically follows redirect
|
15
15
|
|
16
16
|
## Installation
|
17
17
|
|
18
18
|
Add this line to your application's Gemfile:
|
19
19
|
|
20
20
|
```ruby
|
21
|
-
gem
|
21
|
+
gem "aitch"
|
22
22
|
```
|
23
23
|
|
24
24
|
And then execute:
|
@@ -54,6 +54,9 @@ Aitch.configure do |config|
|
|
54
54
|
|
55
55
|
# Set the logger.
|
56
56
|
config.logger = nil
|
57
|
+
|
58
|
+
# Set the base url.
|
59
|
+
config.base_url = nil
|
57
60
|
end
|
58
61
|
```
|
59
62
|
|
@@ -83,6 +86,17 @@ response = Aitch.get do
|
|
83
86
|
end
|
84
87
|
```
|
85
88
|
|
89
|
+
Finally, you can use keyword arguments:
|
90
|
+
|
91
|
+
```ruby
|
92
|
+
Aitch.get(
|
93
|
+
url: "http://example.org",
|
94
|
+
params: {a: 1, b: 2},
|
95
|
+
headers: {Authorization: "Token token=abc"},
|
96
|
+
options: {follow_redirect: false}
|
97
|
+
)
|
98
|
+
```
|
99
|
+
|
86
100
|
### Response
|
87
101
|
|
88
102
|
The response object:
|
@@ -104,7 +118,8 @@ response.data # Parsed response body
|
|
104
118
|
|
105
119
|
#### Parsing JSON, XML and HTML with Nokogiri
|
106
120
|
|
107
|
-
If your response is a JSON, XML or a HTML content type, we'll automatically
|
121
|
+
If your response is a JSON, XML or a HTML content type, we'll automatically
|
122
|
+
convert the response into the appropriate object.
|
108
123
|
|
109
124
|
```ruby
|
110
125
|
response = Aitch.get("http://simplesideias.com.br")
|
@@ -148,7 +163,8 @@ The request:
|
|
148
163
|
Aitch.get("http://example.org")
|
149
164
|
```
|
150
165
|
|
151
|
-
If the redirect limit is exceeded, then the `Aitch::TooManyRedirectsError`
|
166
|
+
If the redirect limit is exceeded, then the `Aitch::TooManyRedirectsError`
|
167
|
+
exception is raised.
|
152
168
|
|
153
169
|
### Basic auth
|
154
170
|
|
@@ -196,7 +212,8 @@ Request.get("http://example.org")
|
|
196
212
|
|
197
213
|
### Validating responses
|
198
214
|
|
199
|
-
When you know the kind of response you're expecting, you can validate it by
|
215
|
+
When you know the kind of response you're expecting, you can validate it by
|
216
|
+
specifying the `expect` option.
|
200
217
|
|
201
218
|
```ruby
|
202
219
|
Aitch.get do
|
@@ -205,7 +222,8 @@ Aitch.get do
|
|
205
222
|
end
|
206
223
|
```
|
207
224
|
|
208
|
-
If this request receives anything other than `200`, it will raise a
|
225
|
+
If this request receives anything other than `200`, it will raise a
|
226
|
+
`Aitch::StatusCodeError` exception.
|
209
227
|
|
210
228
|
```
|
211
229
|
Expect(200 OK) <=> Actual(404 Not Found)
|
@@ -215,7 +233,10 @@ You can also provide a list of accepted statuses, like `expect: [200, 201]`.
|
|
215
233
|
|
216
234
|
### Response Parsers
|
217
235
|
|
218
|
-
You can register new response parsers by using
|
236
|
+
You can register new response parsers by using
|
237
|
+
`Aitch::ResponseParser.register(name, parser)`, where parser must implement the
|
238
|
+
methods `match?(content_type)` and `load(response_body)`. This is how you could
|
239
|
+
load CSV values.
|
219
240
|
|
220
241
|
```ruby
|
221
242
|
require "csv"
|
@@ -237,7 +258,8 @@ end
|
|
237
258
|
Aitch::ResponseParser.prepend(:csv, CSVParser)
|
238
259
|
```
|
239
260
|
|
240
|
-
The default behavior is returning the response body. You can replace it as the
|
261
|
+
The default behavior is returning the response body. You can replace it as the
|
262
|
+
following:
|
241
263
|
|
242
264
|
```ruby
|
243
265
|
module DefaultParser
|
@@ -261,13 +283,31 @@ Aitch::ResponseParser.append(:default, DefaultParser)
|
|
261
283
|
|
262
284
|
Aitch comes with response parsers for HTML, XML and JSON.
|
263
285
|
|
264
|
-
By default, the JSON parser will be `JSON`. To set it to something else, use
|
286
|
+
By default, the JSON parser will be `JSON`. To set it to something else, use
|
287
|
+
`Aitch::ResponseParser::JSONParser.engine`.
|
265
288
|
|
266
289
|
```ruby
|
267
290
|
require "oj"
|
268
291
|
Aitch::ResponseParser::JSONParser.engine = Oj
|
269
292
|
```
|
270
293
|
|
294
|
+
### Setting the base url
|
295
|
+
|
296
|
+
When you're creating a wrapper for an API, usually the hostname is the same for
|
297
|
+
the whole API. In this case, you can avoid having to pass it around all the time
|
298
|
+
by setting `Aitch::Configuration#base_url`. This option is meant to be used when
|
299
|
+
you instantiate a new namespace.
|
300
|
+
|
301
|
+
```ruby
|
302
|
+
Client = Aitch::Namespace.new
|
303
|
+
|
304
|
+
Client.configure do |config|
|
305
|
+
config.base_url = "https://api.example.com"
|
306
|
+
end
|
307
|
+
|
308
|
+
Client.get("/users")
|
309
|
+
```
|
310
|
+
|
271
311
|
## Contributing
|
272
312
|
|
273
313
|
1. Fork it
|
data/Rakefile
CHANGED
@@ -1,6 +1,8 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
|
+
|
2
3
|
require "bundler/gem_tasks"
|
3
4
|
require "rake/testtask"
|
5
|
+
require "rubocop/rake_task"
|
4
6
|
|
5
7
|
Rake::TestTask.new(:test) do |t|
|
6
8
|
t.libs << "test"
|
@@ -8,4 +10,6 @@ Rake::TestTask.new(:test) do |t|
|
|
8
10
|
t.warning = false
|
9
11
|
end
|
10
12
|
|
11
|
-
|
13
|
+
RuboCop::RakeTask.new
|
14
|
+
|
15
|
+
task default: %i[test rubocop]
|
data/aitch.gemspec
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require "./lib/aitch/version"
|
2
4
|
|
3
5
|
Gem::Specification.new do |spec|
|
@@ -9,20 +11,23 @@ Gem::Specification.new do |spec|
|
|
9
11
|
spec.summary = spec.description
|
10
12
|
spec.homepage = "http://rubygems.org/gems/aitch"
|
11
13
|
spec.license = "MIT"
|
14
|
+
spec.required_ruby_version = Gem::Requirement.new(">= 2.5.0")
|
12
15
|
|
13
|
-
spec.files = `git ls-files`.split(
|
14
|
-
spec.executables = spec.files.grep(%r{^bin/}) {
|
16
|
+
spec.files = `git ls-files`.split($INPUT_RECORD_SEPARATOR)
|
17
|
+
spec.executables = spec.files.grep(%r{^bin/}) {|f| File.basename(f) }
|
15
18
|
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
16
19
|
spec.require_paths = ["lib"]
|
17
20
|
|
18
|
-
spec.
|
19
|
-
|
20
|
-
spec.add_dependency "nokogiri", ">= 1.6.0"
|
21
|
+
spec.add_dependency "nokogiri"
|
21
22
|
|
22
|
-
spec.add_development_dependency "codeclimate-test-reporter"
|
23
23
|
spec.add_development_dependency "bundler"
|
24
|
-
spec.add_development_dependency "
|
24
|
+
spec.add_development_dependency "minitest"
|
25
25
|
spec.add_development_dependency "minitest-utils"
|
26
26
|
spec.add_development_dependency "mocha"
|
27
|
+
spec.add_development_dependency "pry-meta"
|
28
|
+
spec.add_development_dependency "rake"
|
29
|
+
spec.add_development_dependency "rubocop"
|
30
|
+
spec.add_development_dependency "rubocop-fnando"
|
31
|
+
spec.add_development_dependency "simplecov"
|
27
32
|
spec.add_development_dependency "webmock"
|
28
33
|
end
|
data/lib/aitch/configuration.rb
CHANGED
@@ -1,4 +1,5 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
|
+
|
2
3
|
module Aitch
|
3
4
|
class Configuration
|
4
5
|
# Set proxy.
|
@@ -22,12 +23,16 @@ module Aitch
|
|
22
23
|
# Set the logger.
|
23
24
|
attr_accessor :logger
|
24
25
|
|
26
|
+
# Set the base url.
|
27
|
+
attr_accessor :base_url
|
28
|
+
|
25
29
|
def initialize
|
26
30
|
@timeout = 10
|
27
31
|
@redirect_limit = 5
|
28
32
|
@follow_redirect = true
|
29
33
|
@user_agent = "Aitch/#{Aitch::VERSION} (http://rubygems.org/gems/aitch)"
|
30
34
|
@default_headers = {}
|
35
|
+
@base_url = nil
|
31
36
|
end
|
32
37
|
|
33
38
|
def to_h
|
data/lib/aitch/dsl.rb
CHANGED
@@ -1,8 +1,9 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
|
+
|
2
3
|
module Aitch
|
3
4
|
class DSL
|
4
5
|
%w[url options headers data].each do |name|
|
5
|
-
class_eval
|
6
|
+
class_eval <<~RUBY, __FILE__, __LINE__ + 1
|
6
7
|
attr_writer :#{name}
|
7
8
|
|
8
9
|
def #{name}(*args)
|
@@ -12,8 +13,8 @@ module Aitch
|
|
12
13
|
RUBY
|
13
14
|
end
|
14
15
|
|
15
|
-
|
16
|
-
|
16
|
+
alias params data
|
17
|
+
alias body data
|
17
18
|
|
18
19
|
def to_h
|
19
20
|
{
|
data/lib/aitch/errors.rb
CHANGED
data/lib/aitch/ext/to_query.rb
CHANGED
@@ -1,4 +1,5 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
|
+
|
2
3
|
require "cgi"
|
3
4
|
|
4
5
|
class Object
|
@@ -36,23 +37,18 @@ class FalseClass
|
|
36
37
|
end
|
37
38
|
|
38
39
|
class Array
|
39
|
-
# Calls <tt>to_param</tt> on all its elements and joins the result with
|
40
|
-
# slashes. This is used by <tt>url_for</tt> in Action Pack.
|
41
|
-
def to_param
|
42
|
-
collect { |e| e.to_param }.join '/'
|
43
|
-
end
|
44
|
-
|
45
40
|
# Converts an array into a string suitable for use as a URL query string,
|
46
41
|
# using the given +key+ as the param name.
|
47
42
|
#
|
48
|
-
# [
|
43
|
+
# ["Rails", "coding"].to_query("hobbies")
|
44
|
+
# # => "hobbies%5B%5D=Rails&hobbies%5B%5D=coding"
|
49
45
|
def to_query(key)
|
50
46
|
prefix = "#{key}[]"
|
51
47
|
|
52
48
|
if empty?
|
53
49
|
nil.to_query(prefix)
|
54
50
|
else
|
55
|
-
collect {
|
51
|
+
collect {|value| value.to_query(prefix) }.join "&"
|
56
52
|
end
|
57
53
|
end
|
58
54
|
end
|
@@ -78,8 +74,8 @@ class Hash
|
|
78
74
|
unless (value.is_a?(Hash) || value.is_a?(Array)) && value.empty?
|
79
75
|
value.to_query(namespace ? "#{namespace}[#{key}]" : key)
|
80
76
|
end
|
81
|
-
end.compact.sort! *
|
77
|
+
end.compact.sort! * "&"
|
82
78
|
end
|
83
79
|
|
84
|
-
|
80
|
+
alias to_param to_query
|
85
81
|
end
|
data/lib/aitch/location.rb
CHANGED
@@ -1,4 +1,5 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
|
+
|
2
3
|
module Aitch
|
3
4
|
class Location
|
4
5
|
attr_reader :redirect_stack, :current_url
|
@@ -9,7 +10,7 @@ module Aitch
|
|
9
10
|
end
|
10
11
|
|
11
12
|
def location
|
12
|
-
return current_url unless current_url.match(%r
|
13
|
+
return current_url unless current_url.match?(%r{\A/}) # rubocop:disable Performance/StartWith
|
13
14
|
|
14
15
|
uri = find_uri_with_host
|
15
16
|
url = ["#{uri.scheme}://#{uri.hostname}"]
|
@@ -20,8 +21,8 @@ module Aitch
|
|
20
21
|
|
21
22
|
def find_uri_with_host
|
22
23
|
redirect_stack.reverse
|
23
|
-
|
24
|
-
|
24
|
+
.map {|url| ::URI.parse(url) }
|
25
|
+
.find(&:scheme)
|
25
26
|
end
|
26
27
|
end
|
27
28
|
end
|
data/lib/aitch/namespace.rb
CHANGED
@@ -1,17 +1,31 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
|
+
|
2
3
|
module Aitch
|
3
4
|
class Namespace
|
4
|
-
def configure
|
5
|
+
def configure
|
5
6
|
yield config
|
6
7
|
end
|
7
8
|
|
8
9
|
def config
|
9
10
|
@config ||= Configuration.new
|
10
11
|
end
|
11
|
-
|
12
|
+
alias configuration config
|
13
|
+
|
14
|
+
def execute(
|
15
|
+
request_method: nil,
|
16
|
+
url: nil,
|
17
|
+
params: nil,
|
18
|
+
data: nil,
|
19
|
+
body: nil,
|
20
|
+
headers: nil,
|
21
|
+
options: nil,
|
22
|
+
&block
|
23
|
+
)
|
24
|
+
data = data || params || body || {}
|
25
|
+
headers ||= {}
|
26
|
+
options ||= {}
|
12
27
|
|
13
|
-
|
14
|
-
if block_given?
|
28
|
+
if block
|
15
29
|
dsl = DSL.new
|
16
30
|
dsl.instance_eval(&block)
|
17
31
|
args = dsl.to_h
|
@@ -24,17 +38,18 @@ module Aitch
|
|
24
38
|
}
|
25
39
|
end
|
26
40
|
|
27
|
-
args
|
28
|
-
|
29
|
-
options: config.to_h.merge(Utils.symbolize_keys(args[:options]))
|
30
|
-
)
|
41
|
+
args[:request_method] = request_method
|
42
|
+
args[:options] = config.to_h.merge(Utils.symbolize_keys(args[:options]))
|
31
43
|
|
32
44
|
Request.new(args).perform
|
33
45
|
end
|
34
46
|
|
35
47
|
def execute!(*args, &block)
|
36
|
-
|
48
|
+
options = extract_args!(args)
|
49
|
+
response = execute(**options, &block)
|
50
|
+
|
37
51
|
raise response.error if response.error?
|
52
|
+
|
38
53
|
response
|
39
54
|
end
|
40
55
|
|
@@ -47,14 +62,23 @@ module Aitch
|
|
47
62
|
options
|
48
63
|
trace
|
49
64
|
head
|
50
|
-
].each do |
|
51
|
-
define_method(
|
52
|
-
|
65
|
+
].each do |request_method|
|
66
|
+
define_method(request_method) do |*args, &block|
|
67
|
+
options = extract_args!(args)
|
68
|
+
execute(**options.merge(request_method: request_method), &block)
|
53
69
|
end
|
54
70
|
|
55
|
-
define_method("#{
|
56
|
-
|
71
|
+
define_method("#{request_method}!") do |*args, &block|
|
72
|
+
options = extract_args!(args)
|
73
|
+
|
74
|
+
execute!(**options.merge(request_method: request_method), &block)
|
57
75
|
end
|
58
76
|
end
|
77
|
+
|
78
|
+
private def extract_args!(args)
|
79
|
+
return args.first if args.size == 1 && args.first.is_a?(Hash)
|
80
|
+
|
81
|
+
%i[url data headers options].zip(args).to_h
|
82
|
+
end
|
59
83
|
end
|
60
84
|
end
|