evil-client 0.3.3 → 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.codeclimate.yml +0 -11
- data/.gitignore +1 -0
- data/.rspec +0 -1
- data/.rubocop.yml +22 -19
- data/.travis.yml +1 -0
- data/CHANGELOG.md +251 -6
- data/LICENSE.txt +3 -1
- data/README.md +47 -81
- data/docs/helpers/body.md +93 -0
- data/docs/helpers/connection.md +19 -0
- data/docs/helpers/headers.md +72 -0
- data/docs/helpers/http_method.md +39 -0
- data/docs/helpers/let.md +14 -0
- data/docs/helpers/logger.md +24 -0
- data/docs/helpers/middleware.md +56 -0
- data/docs/helpers/operation.md +103 -0
- data/docs/helpers/option.md +50 -0
- data/docs/helpers/path.md +37 -0
- data/docs/helpers/query.md +59 -0
- data/docs/helpers/response.md +40 -0
- data/docs/helpers/scope.md +121 -0
- data/docs/helpers/security.md +102 -0
- data/docs/helpers/validate.md +68 -0
- data/docs/index.md +70 -78
- data/docs/license.md +5 -1
- data/docs/rspec.md +96 -0
- data/evil-client.gemspec +10 -8
- data/lib/evil/client.rb +126 -72
- data/lib/evil/client/builder.rb +47 -0
- data/lib/evil/client/builder/operation.rb +40 -0
- data/lib/evil/client/builder/scope.rb +31 -0
- data/lib/evil/client/chaining.rb +17 -0
- data/lib/evil/client/connection.rb +60 -20
- data/lib/evil/client/container.rb +66 -0
- data/lib/evil/client/container/operation.rb +23 -0
- data/lib/evil/client/container/scope.rb +28 -0
- data/lib/evil/client/exceptions/definition_error.rb +15 -0
- data/lib/evil/client/exceptions/name_error.rb +32 -0
- data/lib/evil/client/exceptions/response_error.rb +42 -0
- data/lib/evil/client/exceptions/type_error.rb +29 -0
- data/lib/evil/client/exceptions/validation_error.rb +27 -0
- data/lib/evil/client/formatter.rb +49 -0
- data/lib/evil/client/formatter/form.rb +45 -0
- data/lib/evil/client/formatter/multipart.rb +33 -0
- data/lib/evil/client/formatter/part.rb +66 -0
- data/lib/evil/client/formatter/text.rb +21 -0
- data/lib/evil/client/resolver.rb +84 -0
- data/lib/evil/client/resolver/body.rb +22 -0
- data/lib/evil/client/resolver/format.rb +30 -0
- data/lib/evil/client/resolver/headers.rb +46 -0
- data/lib/evil/client/resolver/http_method.rb +34 -0
- data/lib/evil/client/resolver/middleware.rb +36 -0
- data/lib/evil/client/resolver/query.rb +39 -0
- data/lib/evil/client/resolver/request.rb +96 -0
- data/lib/evil/client/resolver/response.rb +26 -0
- data/lib/evil/client/resolver/security.rb +113 -0
- data/lib/evil/client/resolver/uri.rb +35 -0
- data/lib/evil/client/rspec.rb +127 -0
- data/lib/evil/client/schema.rb +105 -0
- data/lib/evil/client/schema/operation.rb +177 -0
- data/lib/evil/client/schema/scope.rb +73 -0
- data/lib/evil/client/settings.rb +172 -0
- data/lib/evil/client/settings/validator.rb +64 -0
- data/mkdocs.yml +21 -15
- data/spec/features/custom_connection_spec.rb +17 -0
- data/spec/features/operation/middleware_spec.rb +50 -0
- data/spec/features/operation/options_spec.rb +71 -0
- data/spec/features/operation/request_spec.rb +94 -0
- data/spec/features/operation/response_spec.rb +48 -0
- data/spec/features/scope/options_spec.rb +52 -0
- data/spec/fixtures/locales/en.yml +16 -0
- data/spec/fixtures/test_client.rb +76 -0
- data/spec/spec_helper.rb +18 -6
- data/spec/support/fixtures_helper.rb +7 -0
- data/spec/unit/builder/operation_spec.rb +90 -0
- data/spec/unit/builder/scope_spec.rb +84 -0
- data/spec/unit/client_spec.rb +137 -0
- data/spec/unit/connection_spec.rb +78 -0
- data/spec/unit/container/operation_spec.rb +81 -0
- data/spec/unit/container/scope_spec.rb +61 -0
- data/spec/unit/container_spec.rb +107 -0
- data/spec/unit/exceptions/definition_error_spec.rb +15 -0
- data/spec/unit/exceptions/name_error_spec.rb +77 -0
- data/spec/unit/exceptions/response_error_spec.rb +22 -0
- data/spec/unit/exceptions/type_error_spec.rb +71 -0
- data/spec/unit/exceptions/validation_error_spec.rb +13 -0
- data/spec/unit/formatter/form_spec.rb +27 -0
- data/spec/unit/formatter/multipart_spec.rb +23 -0
- data/spec/unit/formatter/part_spec.rb +49 -0
- data/spec/unit/formatter/text_spec.rb +37 -0
- data/spec/unit/formatter_spec.rb +46 -0
- data/spec/unit/resolver/body_spec.rb +65 -0
- data/spec/unit/resolver/format_spec.rb +66 -0
- data/spec/unit/resolver/headers_spec.rb +93 -0
- data/spec/unit/resolver/http_method_spec.rb +67 -0
- data/spec/unit/resolver/middleware_spec.rb +83 -0
- data/spec/unit/resolver/query_spec.rb +85 -0
- data/spec/unit/resolver/request_spec.rb +121 -0
- data/spec/unit/resolver/response_spec.rb +64 -0
- data/spec/unit/resolver/security_spec.rb +156 -0
- data/spec/unit/resolver/uri_spec.rb +117 -0
- data/spec/unit/rspec_spec.rb +342 -0
- data/spec/unit/schema/operation_spec.rb +309 -0
- data/spec/unit/schema/scope_spec.rb +110 -0
- data/spec/unit/schema_spec.rb +157 -0
- data/spec/unit/settings/validator_spec.rb +128 -0
- data/spec/unit/settings_spec.rb +248 -0
- metadata +192 -135
- data/docs/base_url.md +0 -38
- data/docs/documentation.md +0 -9
- data/docs/headers.md +0 -59
- data/docs/http_method.md +0 -31
- data/docs/model.md +0 -173
- data/docs/operation.md +0 -0
- data/docs/overview.md +0 -0
- data/docs/path.md +0 -48
- data/docs/query.md +0 -99
- data/docs/responses.md +0 -66
- data/docs/security.md +0 -102
- data/docs/settings.md +0 -32
- data/lib/evil/client/connection/net_http.rb +0 -57
- data/lib/evil/client/dsl.rb +0 -127
- data/lib/evil/client/dsl/base.rb +0 -26
- data/lib/evil/client/dsl/files.rb +0 -37
- data/lib/evil/client/dsl/headers.rb +0 -16
- data/lib/evil/client/dsl/http_method.rb +0 -24
- data/lib/evil/client/dsl/operation.rb +0 -91
- data/lib/evil/client/dsl/operations.rb +0 -41
- data/lib/evil/client/dsl/path.rb +0 -25
- data/lib/evil/client/dsl/query.rb +0 -16
- data/lib/evil/client/dsl/response.rb +0 -61
- data/lib/evil/client/dsl/responses.rb +0 -29
- data/lib/evil/client/dsl/scope.rb +0 -27
- data/lib/evil/client/dsl/security.rb +0 -57
- data/lib/evil/client/dsl/verifier.rb +0 -35
- data/lib/evil/client/middleware.rb +0 -81
- data/lib/evil/client/middleware/base.rb +0 -11
- data/lib/evil/client/middleware/merge_security.rb +0 -20
- data/lib/evil/client/middleware/normalize_headers.rb +0 -17
- data/lib/evil/client/middleware/stringify_form.rb +0 -40
- data/lib/evil/client/middleware/stringify_json.rb +0 -19
- data/lib/evil/client/middleware/stringify_multipart.rb +0 -36
- data/lib/evil/client/middleware/stringify_multipart/part.rb +0 -36
- data/lib/evil/client/middleware/stringify_query.rb +0 -35
- data/lib/evil/client/operation.rb +0 -34
- data/lib/evil/client/operation/request.rb +0 -26
- data/lib/evil/client/operation/response.rb +0 -39
- data/lib/evil/client/operation/response_error.rb +0 -13
- data/lib/evil/client/operation/unexpected_response_error.rb +0 -19
- data/spec/features/instantiation_spec.rb +0 -68
- data/spec/features/middleware_spec.rb +0 -79
- data/spec/features/operation_with_documentation_spec.rb +0 -41
- data/spec/features/operation_with_files_spec.rb +0 -40
- data/spec/features/operation_with_form_body_spec.rb +0 -158
- data/spec/features/operation_with_headers_spec.rb +0 -99
- data/spec/features/operation_with_http_method_spec.rb +0 -45
- data/spec/features/operation_with_json_body_spec.rb +0 -156
- data/spec/features/operation_with_nested_responses_spec.rb +0 -95
- data/spec/features/operation_with_path_spec.rb +0 -47
- data/spec/features/operation_with_query_spec.rb +0 -84
- data/spec/features/operation_with_security_spec.rb +0 -228
- data/spec/features/scoping_spec.rb +0 -48
- data/spec/support/test_client.rb +0 -15
- data/spec/unit/evil/client/connection/net_http_spec.rb +0 -38
- data/spec/unit/evil/client/dsl/files_spec.rb +0 -37
- data/spec/unit/evil/client/dsl/operation_spec.rb +0 -374
- data/spec/unit/evil/client/dsl/operations_spec.rb +0 -29
- data/spec/unit/evil/client/dsl/scope_spec.rb +0 -32
- data/spec/unit/evil/client/dsl/security_spec.rb +0 -135
- data/spec/unit/evil/client/middleware/merge_security_spec.rb +0 -32
- data/spec/unit/evil/client/middleware/normalize_headers_spec.rb +0 -17
- data/spec/unit/evil/client/middleware/stringify_form_spec.rb +0 -63
- data/spec/unit/evil/client/middleware/stringify_json_spec.rb +0 -61
- data/spec/unit/evil/client/middleware/stringify_multipart/part_spec.rb +0 -59
- data/spec/unit/evil/client/middleware/stringify_multipart_spec.rb +0 -62
- data/spec/unit/evil/client/middleware/stringify_query_spec.rb +0 -40
- data/spec/unit/evil/client/middleware_spec.rb +0 -46
- data/spec/unit/evil/client/operation/request_spec.rb +0 -49
- data/spec/unit/evil/client/operation/response_spec.rb +0 -63
data/docs/license.md
CHANGED
@@ -1,4 +1,8 @@
|
|
1
|
-
|
1
|
+
# The MIT License (MIT)
|
2
|
+
|
3
|
+
Copyright (c) 2015-2017 Andrew Kozin (nepalez),
|
4
|
+
Ravil Bairamgalin (brainopia),
|
5
|
+
Evil Martians (evilmartians)
|
2
6
|
|
3
7
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
4
8
|
of this software and associated documentation files (the "Software"), to deal
|
data/docs/rspec.md
ADDED
@@ -0,0 +1,96 @@
|
|
1
|
+
When you provide a client to remote API, you would provide some means for its users to test their operations.
|
2
|
+
|
3
|
+
Surely, they could use [webmock] to check the ultimate requests that are sent to the server. But doing this, they would inadvertedly specify not their own code, but your client's code too. What do they actually need is a means to check calls of your client's operations. This way they would back on correctness of your client, and take its interface as an endpoint.
|
4
|
+
|
5
|
+
For this reason, we support a special RSpec matcher `perform_operation`. It checks, what operations are called via evil-client, and what options are used in there.
|
6
|
+
|
7
|
+
The matcher isn't loaded by default, so you must require it first:
|
8
|
+
|
9
|
+
```ruby
|
10
|
+
require "evil/client/rspec"
|
11
|
+
```
|
12
|
+
|
13
|
+
Providing that you defined some client...
|
14
|
+
|
15
|
+
```ruby
|
16
|
+
class CatsClient < Evil::Client
|
17
|
+
option :token
|
18
|
+
# ...
|
19
|
+
scope :cats do
|
20
|
+
option :version
|
21
|
+
# ...
|
22
|
+
operation :fetch do
|
23
|
+
option :id
|
24
|
+
# ...
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
```
|
29
|
+
|
30
|
+
... lets write a specification:
|
31
|
+
|
32
|
+
```ruby
|
33
|
+
require "evil/client/rspec"
|
34
|
+
|
35
|
+
RSpec.describe CatsClient, "cats.fetch" do
|
36
|
+
let(:client) { CatsClient.new(token: "foo") }
|
37
|
+
let(:scope) { client.cats(version: 1) }
|
38
|
+
|
39
|
+
it "fetches a cat by id" do
|
40
|
+
expect { scope.fetch(id: 8) }
|
41
|
+
.to perform_operation("CatsClient.client.fetch")
|
42
|
+
end
|
43
|
+
end
|
44
|
+
```
|
45
|
+
|
46
|
+
You can add chaining using one of 3 additional methods: `with`, `with_exactly`, or `without`.
|
47
|
+
|
48
|
+
## with
|
49
|
+
|
50
|
+
This method checks that the operation **includes some options**:
|
51
|
+
|
52
|
+
```ruby
|
53
|
+
expect { scope.fetch(id: 8) }
|
54
|
+
.to perform_operation("CatsClient.client.fetch")
|
55
|
+
.with token: "foo"
|
56
|
+
```
|
57
|
+
|
58
|
+
## with_exactly
|
59
|
+
|
60
|
+
This time you can check the full list of options given to operation:
|
61
|
+
|
62
|
+
```ruby
|
63
|
+
expect { scope.fetch(id: 8) }
|
64
|
+
.to perform_operation("CatsClient.client.fetch")
|
65
|
+
.with_exactly token: "foo", version: 1, id: 8
|
66
|
+
```
|
67
|
+
|
68
|
+
## without
|
69
|
+
|
70
|
+
You can also check that some keys are absent:
|
71
|
+
|
72
|
+
```ruby
|
73
|
+
expect { scope.fetch(id: 8) }
|
74
|
+
.to perform_operation("CatsClient.client.fetch")
|
75
|
+
.without :name, :email
|
76
|
+
```
|
77
|
+
|
78
|
+
This can be useful to check a behaviour of the client with optional attributes.
|
79
|
+
|
80
|
+
All checks can be negated as well:
|
81
|
+
|
82
|
+
```ruby
|
83
|
+
expect { scope.fetch(id: 8) }
|
84
|
+
.not_to perform_operation("CatsClient.client.fetch")
|
85
|
+
.with token: "foo"
|
86
|
+
```
|
87
|
+
|
88
|
+
**Notice**: Under the hood the matcher doesn't stub the request, so its better to stub all requests by hand:
|
89
|
+
|
90
|
+
```ruby
|
91
|
+
require "webmock/rspec"
|
92
|
+
|
93
|
+
before { stub_request :any, // }
|
94
|
+
```
|
95
|
+
|
96
|
+
[webmock]: https://github.com/bblimke/webmock
|
data/evil-client.gemspec
CHANGED
@@ -1,8 +1,8 @@
|
|
1
1
|
Gem::Specification.new do |gem|
|
2
2
|
gem.name = "evil-client"
|
3
|
-
gem.version = "0.
|
3
|
+
gem.version = "1.0.0"
|
4
4
|
gem.author = ["Andrew Kozin (nepalez)", "Ravil Bairamgalin (brainopia)"]
|
5
|
-
gem.email = "andrew.kozin@gmail.com"
|
5
|
+
gem.email = ["andrew.kozin@gmail.com", "nepalez@evilmartians.com"]
|
6
6
|
gem.homepage = "https://github.com/evilmartians/evil-client"
|
7
7
|
gem.summary = "Human-friendly DSL for building HTTP(s) clients in Ruby"
|
8
8
|
gem.license = "MIT"
|
@@ -13,13 +13,15 @@ Gem::Specification.new do |gem|
|
|
13
13
|
|
14
14
|
gem.required_ruby_version = ">= 2.3"
|
15
15
|
|
16
|
-
gem.add_runtime_dependency "
|
17
|
-
gem.add_runtime_dependency "
|
18
|
-
gem.add_runtime_dependency "
|
16
|
+
gem.add_runtime_dependency "dry-initializer", "~> 1.4"
|
17
|
+
gem.add_runtime_dependency "i18n", "~> 0.8.6"
|
18
|
+
gem.add_runtime_dependency "mime-types", "~> 3.1"
|
19
|
+
gem.add_runtime_dependency "rack", "~> 1"
|
19
20
|
|
20
|
-
gem.add_development_dependency "
|
21
|
+
gem.add_development_dependency "rake", ">= 10"
|
21
22
|
gem.add_development_dependency "rspec", "~> 3.0"
|
22
|
-
gem.add_development_dependency "
|
23
|
+
gem.add_development_dependency "rspec-its", "~> 1.2"
|
24
|
+
gem.add_development_dependency "rubocop", "~> 0.42"
|
25
|
+
gem.add_development_dependency "timecop", "~> 0.9"
|
23
26
|
gem.add_development_dependency "webmock", "~> 2.1"
|
24
|
-
gem.add_development_dependency "rubocop", "~> 0.44"
|
25
27
|
end
|
data/lib/evil/client.rb
CHANGED
@@ -1,83 +1,137 @@
|
|
1
|
-
require "
|
2
|
-
require "
|
1
|
+
require "uri"
|
2
|
+
require "logger"
|
3
3
|
require "rack"
|
4
|
+
require "cgi"
|
4
5
|
require "json"
|
6
|
+
require "yaml"
|
7
|
+
require "i18n"
|
8
|
+
require "mime-types"
|
5
9
|
require "securerandom"
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
# @abstract
|
10
|
-
# @example
|
11
|
-
# class MyClient < Evil::Client
|
12
|
-
# # declare settings for the client's constructor
|
13
|
-
# # the settings parameterize the rest of the client's definitions
|
14
|
-
# settings do
|
15
|
-
# option :version, type: Dry::Types["strict.int"].default(1)
|
16
|
-
# option :user, type: Dry::Types["strict.string"]
|
17
|
-
# option :token, type: Dry::Types["strict.string"]
|
18
|
-
# end
|
19
|
-
#
|
20
|
-
# # define base url of the server
|
21
|
-
# base_url do |settings|
|
22
|
-
# "https://my_api.com/v#{settings.version}"
|
23
|
-
# end
|
24
|
-
#
|
25
|
-
# # define connection and its middleware stack from bottom to top
|
26
|
-
# connection :net_http do |settings|
|
27
|
-
# run AddCustomRequestId
|
28
|
-
# run EncryptToken if settings.token
|
29
|
-
# end
|
30
|
-
#
|
31
|
-
# # definitions shared by all operations (can be reloaded later)
|
32
|
-
# operation do |settings|
|
33
|
-
# type { :json }
|
34
|
-
# security { basic_auth "foo", "bar" }
|
35
|
-
# end
|
36
|
-
#
|
37
|
-
# # operation-specific definitions
|
38
|
-
# operation :find_cat do |settings|
|
39
|
-
# http_method :get
|
40
|
-
# path { "#{settings.url}/cats/find/#{id}" }
|
10
|
+
require "dry-initializer"
|
11
|
+
require "net/http"
|
12
|
+
require "net/https"
|
41
13
|
#
|
42
|
-
#
|
43
|
-
# option :id, type: Dry::Types["coercible.int"].constrained(gt: 0)
|
44
|
-
# end
|
45
|
-
#
|
46
|
-
# response 200, type: Cat
|
47
|
-
# response 400, raise: true
|
48
|
-
# response 422, raise: true do |body:|
|
49
|
-
# JSON.parse(body.first)
|
50
|
-
# end
|
51
|
-
# end
|
52
|
-
#
|
53
|
-
# # top-level DSL for operation
|
54
|
-
# scope :users do
|
55
|
-
# scope do # named `:[]` by default
|
56
|
-
# param :id, type: Dry::Types["strict.int"]
|
57
|
-
#
|
58
|
-
# def get
|
59
|
-
# operations[:find_users].call(id: id)
|
60
|
-
# end
|
61
|
-
# end
|
62
|
-
# end
|
63
|
-
# end
|
64
|
-
#
|
65
|
-
# # Initialize a client with a corresponding settings
|
66
|
-
# client = MyClient.new user: "andrew", token: "f982j23"
|
67
|
-
#
|
68
|
-
# # Use low-level DSL for searching a user
|
69
|
-
# client.operations[:find_user].call(id: 1)
|
70
|
-
#
|
71
|
-
# # Use top-level DSL for the same operation
|
72
|
-
# client.users[1].get
|
14
|
+
# Namespace for gems created by Evil Martians
|
73
15
|
#
|
74
16
|
module Evil
|
17
|
+
#
|
18
|
+
# Absctract base class for clients to remote APIs
|
19
|
+
#
|
75
20
|
class Client
|
21
|
+
require_relative "client/exceptions/definition_error"
|
22
|
+
require_relative "client/exceptions/name_error"
|
23
|
+
require_relative "client/exceptions/response_error"
|
24
|
+
require_relative "client/exceptions/type_error"
|
25
|
+
require_relative "client/exceptions/validation_error"
|
26
|
+
|
27
|
+
require_relative "client/chaining"
|
28
|
+
require_relative "client/settings"
|
29
|
+
require_relative "client/schema"
|
30
|
+
require_relative "client/container"
|
31
|
+
require_relative "client/builder"
|
76
32
|
require_relative "client/connection"
|
77
|
-
require_relative "client/
|
78
|
-
require_relative "client/
|
79
|
-
|
33
|
+
require_relative "client/formatter"
|
34
|
+
require_relative "client/resolver"
|
35
|
+
|
36
|
+
include Chaining
|
37
|
+
|
38
|
+
class << self
|
39
|
+
# Object used as an HTTP(s) connection to remote API
|
40
|
+
#
|
41
|
+
# It is expected to implement the method [#call] which
|
42
|
+
# should take one argument for a rack-compatible request environment,
|
43
|
+
# and return a rack-compatible response.
|
44
|
+
#
|
45
|
+
# By default the connection is set to [Evil::Client::Connection],
|
46
|
+
# but it can be redefined for a custom client.
|
47
|
+
#
|
48
|
+
# @return [#call] connection (Evil::Client::Connection)
|
49
|
+
#
|
50
|
+
def connection
|
51
|
+
@connection ||= Evil::Client::Connection
|
52
|
+
end
|
53
|
+
|
54
|
+
# Sets a custom connection, or resets it to a default one
|
55
|
+
#
|
56
|
+
# @param [#call, nil] connection
|
57
|
+
# @return [self]
|
58
|
+
#
|
59
|
+
def connection=(connection)
|
60
|
+
@connection = connection
|
61
|
+
self
|
62
|
+
end
|
63
|
+
|
64
|
+
# Schema for the root scope of the client
|
65
|
+
#
|
66
|
+
# @return [Evil::Client::Schema::Scope]
|
67
|
+
#
|
68
|
+
def schema
|
69
|
+
@schema ||= Schema::Scope.new(self)
|
70
|
+
end
|
71
|
+
|
72
|
+
private
|
73
|
+
|
74
|
+
def respond_to_missing?(name, *)
|
75
|
+
schema.respond_to? name
|
76
|
+
end
|
77
|
+
|
78
|
+
def method_missing(*args, &block)
|
79
|
+
respond_to_missing?(*args) ? schema.send(*args, &block) : super
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
# Initialized root scope container
|
84
|
+
#
|
85
|
+
# @return [Evil::Client::Container::Scope]
|
86
|
+
#
|
87
|
+
attr_reader :scope
|
88
|
+
|
89
|
+
# Logger for the root scope
|
90
|
+
#
|
91
|
+
# @return (see Evil::Client::Settings#logger)
|
92
|
+
#
|
93
|
+
def logger
|
94
|
+
@scope.logger
|
95
|
+
end
|
96
|
+
|
97
|
+
# Sets logger to the client
|
98
|
+
#
|
99
|
+
# @param [Logger, nil] logger
|
100
|
+
# @return [self]
|
101
|
+
#
|
102
|
+
def logger=(logger)
|
103
|
+
@scope.logger = logger
|
104
|
+
self
|
105
|
+
end
|
106
|
+
|
107
|
+
# Operations defined at the root of the client
|
108
|
+
#
|
109
|
+
# @return (see Evil::Client::Container::Scope#operations)
|
110
|
+
#
|
111
|
+
def operations
|
112
|
+
@scope.operations
|
113
|
+
end
|
114
|
+
|
115
|
+
# Subscopes of client root
|
116
|
+
#
|
117
|
+
# @return (see Evil::Client::Container::Scope#scopes)
|
118
|
+
#
|
119
|
+
def scopes
|
120
|
+
@scope.scopes
|
121
|
+
end
|
122
|
+
|
123
|
+
# Options assigned to the client
|
124
|
+
#
|
125
|
+
# @return (see Evil::Client::Container#options)
|
126
|
+
#
|
127
|
+
def options
|
128
|
+
@scope.options
|
129
|
+
end
|
130
|
+
|
131
|
+
private
|
80
132
|
|
81
|
-
|
133
|
+
def initialize(**options)
|
134
|
+
@scope = Container::Scope.new self.class.send(:schema), options
|
135
|
+
end
|
82
136
|
end
|
83
137
|
end
|
@@ -0,0 +1,47 @@
|
|
1
|
+
class Evil::Client
|
2
|
+
#
|
3
|
+
# @abstract
|
4
|
+
# Base class for scope/operation builders
|
5
|
+
#
|
6
|
+
# Every builder just wraps scope/operation schema along with
|
7
|
+
# preinitialized [#parent] settings of its super-scope.
|
8
|
+
# The instance method [#new] quacks like the lazy constructor
|
9
|
+
# for scope/operation instance whose options reload the [#parent]'s ones.
|
10
|
+
#
|
11
|
+
class Builder
|
12
|
+
# Load concrete implementations for the abstact builder
|
13
|
+
require_relative "builder/scope"
|
14
|
+
require_relative "builder/operation"
|
15
|
+
|
16
|
+
# The schema for an instance to be constructed via [#new]
|
17
|
+
# @return [Evil::Client::Schema]
|
18
|
+
attr_reader :schema
|
19
|
+
|
20
|
+
# The instance of parent scope carrying default settings
|
21
|
+
# @return [Evil::Client::Container::Scope]
|
22
|
+
attr_reader :parent
|
23
|
+
|
24
|
+
# Alias method for [#to_s]
|
25
|
+
#
|
26
|
+
# @return [String]
|
27
|
+
#
|
28
|
+
def to_str
|
29
|
+
to_s
|
30
|
+
end
|
31
|
+
|
32
|
+
# Alias method for [#to_s]
|
33
|
+
#
|
34
|
+
# @return [String]
|
35
|
+
#
|
36
|
+
def inspect
|
37
|
+
to_s
|
38
|
+
end
|
39
|
+
|
40
|
+
private
|
41
|
+
|
42
|
+
def initialize(schema, parent)
|
43
|
+
@schema = schema
|
44
|
+
@parent = parent
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
class Evil::Client
|
2
|
+
#
|
3
|
+
# Lazy container for a [#schema] and [#parent] settings
|
4
|
+
# of a [#new] operation to be initialized with its own options,
|
5
|
+
# that reload the [#parent] ones.
|
6
|
+
#
|
7
|
+
class Builder::Operation < Builder
|
8
|
+
# Human-readable representation of the handler
|
9
|
+
#
|
10
|
+
# @example
|
11
|
+
# '#<MyClient.scopes[:users] @version="1.1">.operations[:fetch]'
|
12
|
+
#
|
13
|
+
# @return [String]
|
14
|
+
#
|
15
|
+
def to_s
|
16
|
+
"#{parent}.operations[:#{schema.name}]"
|
17
|
+
end
|
18
|
+
|
19
|
+
# @!method new(options)
|
20
|
+
# Builds new operation with options reloading those of its [#parent]
|
21
|
+
#
|
22
|
+
# @param [Hash<Symbol, Object>] options ({}) Custom options
|
23
|
+
# @return [Evil::Client::Container::Operation]
|
24
|
+
#
|
25
|
+
def new(**options)
|
26
|
+
Container::Operation.new schema, parent.options.merge(options)
|
27
|
+
end
|
28
|
+
|
29
|
+
# @!method call(options)
|
30
|
+
# Builds and calls operation at once
|
31
|
+
#
|
32
|
+
# @param (see #new)
|
33
|
+
# @return (see Container::Operation#call)
|
34
|
+
#
|
35
|
+
def call(**options)
|
36
|
+
new(**options).call
|
37
|
+
end
|
38
|
+
alias_method :[], :call
|
39
|
+
end
|
40
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
class Evil::Client
|
2
|
+
#
|
3
|
+
# Lazy container for a [#schema] and [#parent] settings
|
4
|
+
# of a [#new] scope to be initialized with its own options,
|
5
|
+
# that reload the [#parent] ones.
|
6
|
+
#
|
7
|
+
class Builder::Scope < Builder
|
8
|
+
# Human-readable representation of the handler
|
9
|
+
#
|
10
|
+
# @example
|
11
|
+
# '#<MyClient.scopes[:crm] @version="1.1">.scopes[:users]'
|
12
|
+
#
|
13
|
+
# @return [String]
|
14
|
+
#
|
15
|
+
def to_s
|
16
|
+
"#{parent}.scopes[:#{schema.name}]"
|
17
|
+
end
|
18
|
+
|
19
|
+
# @!method new(options)
|
20
|
+
# Builds new scope with options reloading those of its [#parent]
|
21
|
+
#
|
22
|
+
# @param [Hash<Symbol, Object>] options Custom options
|
23
|
+
# @return [Evil::Client::Container::Scope]
|
24
|
+
#
|
25
|
+
def new(**options)
|
26
|
+
Container::Scope.new schema, parent.options.merge(options)
|
27
|
+
end
|
28
|
+
alias_method :call, :new
|
29
|
+
alias_method :[], :new
|
30
|
+
end
|
31
|
+
end
|