rails-graphql 0.2.1 → 1.0.0.rc1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/ext/console.rb +18 -0
- data/ext/extconf.h +3 -0
- data/ext/extconf.rb +1 -54
- data/ext/gql_parser.c +631 -0
- data/ext/gql_parser.h +21 -0
- data/ext/shared.c +477 -0
- data/ext/shared.h +177 -0
- data/lib/generators/graphql/channel_generator.rb +27 -0
- data/lib/generators/graphql/controller_generator.rb +9 -4
- data/lib/generators/graphql/install_generator.rb +49 -0
- data/lib/generators/graphql/schema_generator.rb +9 -4
- data/lib/generators/graphql/templates/channel.erb +7 -0
- data/lib/generators/graphql/templates/config.rb +97 -0
- data/lib/generators/graphql/templates/controller.erb +2 -0
- data/lib/generators/graphql/templates/schema.erb +5 -3
- data/lib/gql_parser.so +0 -0
- data/lib/rails/graphql/adapters/mysql_adapter.rb +59 -0
- data/lib/rails/graphql/adapters/pg_adapter.rb +25 -22
- data/lib/rails/graphql/adapters/sqlite_adapter.rb +17 -14
- data/lib/rails/graphql/alternative/field_set.rb +48 -0
- data/lib/rails/graphql/alternative/mutation.rb +17 -0
- data/lib/rails/graphql/alternative/query.rb +98 -0
- data/lib/rails/graphql/alternative/subscription.rb +18 -0
- data/lib/rails/graphql/alternative.rb +20 -0
- data/lib/rails/graphql/argument.rb +25 -26
- data/lib/rails/graphql/callback.rb +30 -14
- data/lib/rails/graphql/collectors/hash_collector.rb +26 -7
- data/lib/rails/graphql/collectors/idented_collector.rb +10 -7
- data/lib/rails/graphql/collectors/json_collector.rb +43 -17
- data/lib/rails/graphql/collectors.rb +4 -4
- data/lib/rails/graphql/config.rb +154 -23
- data/lib/rails/graphql/directive/cached_directive.rb +33 -0
- data/lib/rails/graphql/directive/deprecated_directive.rb +10 -10
- data/lib/rails/graphql/directive/include_directive.rb +4 -4
- data/lib/rails/graphql/directive/skip_directive.rb +4 -4
- data/lib/rails/graphql/directive/specified_by_directive.rb +24 -0
- data/lib/rails/graphql/directive.rb +134 -73
- data/lib/rails/graphql/errors.rb +33 -4
- data/lib/rails/graphql/event.rb +21 -9
- data/lib/rails/graphql/field/authorized_field.rb +17 -6
- data/lib/rails/graphql/field/input_field.rb +8 -12
- data/lib/rails/graphql/field/mutation_field.rb +43 -9
- data/lib/rails/graphql/field/output_field.rb +112 -12
- data/lib/rails/graphql/field/proxied_field.rb +35 -26
- data/lib/rails/graphql/field/resolved_field.rb +27 -25
- data/lib/rails/graphql/field/scoped_config.rb +10 -4
- data/lib/rails/graphql/field/subscription_field.rb +123 -0
- data/lib/rails/graphql/field/typed_field.rb +69 -24
- data/lib/rails/graphql/field.rb +89 -74
- data/lib/rails/graphql/global_id.rb +89 -0
- data/lib/rails/graphql/helpers/attribute_delegator.rb +5 -5
- data/lib/rails/graphql/helpers/inherited_collection/array.rb +51 -0
- data/lib/rails/graphql/helpers/inherited_collection/base.rb +45 -0
- data/lib/rails/graphql/helpers/inherited_collection/hash.rb +88 -0
- data/lib/rails/graphql/helpers/inherited_collection.rb +25 -76
- data/lib/rails/graphql/helpers/instantiable.rb +15 -0
- data/lib/rails/graphql/helpers/leaf_from_ar.rb +7 -7
- data/lib/rails/graphql/helpers/registerable.rb +44 -62
- data/lib/rails/graphql/helpers/unregisterable.rb +16 -0
- data/lib/rails/graphql/helpers/with_arguments.rb +33 -28
- data/lib/rails/graphql/helpers/with_assignment.rb +6 -6
- data/lib/rails/graphql/helpers/with_callbacks.rb +28 -11
- data/lib/rails/graphql/helpers/with_description.rb +73 -0
- data/lib/rails/graphql/helpers/with_directives.rb +58 -30
- data/lib/rails/graphql/helpers/with_events.rb +22 -23
- data/lib/rails/graphql/helpers/with_fields.rb +86 -26
- data/lib/rails/graphql/helpers/with_global_id.rb +22 -0
- data/lib/rails/graphql/helpers/with_name.rb +44 -0
- data/lib/rails/graphql/helpers/with_namespace.rb +7 -4
- data/lib/rails/graphql/helpers/with_owner.rb +8 -7
- data/lib/rails/graphql/helpers/with_schema_fields.rb +162 -56
- data/lib/rails/graphql/helpers/with_validator.rb +9 -9
- data/lib/rails/graphql/helpers.rb +10 -3
- data/lib/rails/graphql/introspection.rb +43 -36
- data/lib/rails/graphql/railtie.rb +89 -33
- data/lib/rails/graphql/railties/app/base_channel.rb +10 -0
- data/lib/rails/graphql/railties/app/base_controller.rb +12 -0
- data/lib/rails/graphql/railties/app/views/_cable.js.erb +56 -0
- data/lib/rails/graphql/railties/app/views/_fetch.js.erb +20 -0
- data/lib/rails/graphql/railties/app/views/graphiql.html.erb +101 -0
- data/lib/rails/graphql/railties/base_generator.rb +5 -17
- data/lib/rails/graphql/railties/channel.rb +157 -0
- data/lib/rails/graphql/railties/controller.rb +91 -25
- data/lib/rails/graphql/railties/controller_runtime.rb +5 -5
- data/lib/rails/graphql/railties/log_subscriber.rb +81 -14
- data/lib/rails/graphql/request/arguments.rb +26 -50
- data/lib/rails/graphql/request/backtrace.rb +212 -0
- data/lib/rails/graphql/request/component/field.rb +98 -70
- data/lib/rails/graphql/request/component/fragment.rb +80 -26
- data/lib/rails/graphql/request/component/operation/subscription.rb +162 -4
- data/lib/rails/graphql/request/component/operation.rb +73 -34
- data/lib/rails/graphql/request/component/spread.rb +79 -27
- data/lib/rails/graphql/request/component/typename.rb +28 -13
- data/lib/rails/graphql/request/component.rb +77 -36
- data/lib/rails/graphql/request/context.rb +19 -9
- data/lib/rails/graphql/request/errors.rb +16 -6
- data/lib/rails/graphql/request/event.rb +23 -8
- data/lib/rails/graphql/request/helpers/directives.rb +69 -27
- data/lib/rails/graphql/request/helpers/selection_set.rb +57 -25
- data/lib/rails/graphql/request/helpers/value_writers.rb +24 -19
- data/lib/rails/graphql/request/prepared_data.rb +100 -0
- data/lib/rails/graphql/request/steps/authorizable.rb +24 -14
- data/lib/rails/graphql/request/steps/organizable.rb +111 -49
- data/lib/rails/graphql/request/steps/{prepareable.rb → preparable.rb} +21 -8
- data/lib/rails/graphql/request/steps/{resolveable.rb → resolvable.rb} +16 -7
- data/lib/rails/graphql/request/strategy/cached_strategy.rb +64 -0
- data/lib/rails/graphql/request/strategy/dynamic_instance.rb +6 -6
- data/lib/rails/graphql/request/strategy/multi_query_strategy.rb +6 -13
- data/lib/rails/graphql/request/strategy/sequenced_strategy.rb +9 -9
- data/lib/rails/graphql/request/strategy.rb +147 -77
- data/lib/rails/graphql/request/subscription.rb +82 -0
- data/lib/rails/graphql/request.rb +353 -104
- data/lib/rails/graphql/schema.rb +251 -106
- data/lib/rails/graphql/shortcuts.rb +33 -8
- data/lib/rails/graphql/source/active_record/builders.rb +64 -51
- data/lib/rails/graphql/source/active_record_source.rb +158 -82
- data/lib/rails/graphql/source/base.rb +83 -0
- data/lib/rails/graphql/source/builder.rb +115 -0
- data/lib/rails/graphql/source/scoped_arguments.rb +39 -21
- data/lib/rails/graphql/source.rb +90 -228
- data/lib/rails/graphql/subscription/provider/action_cable.rb +113 -0
- data/lib/rails/graphql/subscription/provider/base.rb +192 -0
- data/lib/rails/graphql/subscription/provider.rb +18 -0
- data/lib/rails/graphql/subscription/store/base.rb +141 -0
- data/lib/rails/graphql/subscription/store/memory.rb +136 -0
- data/lib/rails/graphql/subscription/store.rb +19 -0
- data/lib/rails/graphql/subscription.rb +17 -0
- data/lib/rails/graphql/to_gql.rb +29 -32
- data/lib/rails/graphql/type/creator.rb +196 -0
- data/lib/rails/graphql/type/enum/directive_location_enum.rb +11 -11
- data/lib/rails/graphql/type/enum/type_kind_enum.rb +3 -3
- data/lib/rails/graphql/type/enum.rb +44 -50
- data/lib/rails/graphql/type/input.rb +92 -25
- data/lib/rails/graphql/type/interface.rb +29 -28
- data/lib/rails/graphql/type/object/directive_object.rb +10 -9
- data/lib/rails/graphql/type/object/enum_value_object.rb +3 -3
- data/lib/rails/graphql/type/object/field_object.rb +24 -6
- data/lib/rails/graphql/type/object/input_value_object.rb +6 -7
- data/lib/rails/graphql/type/object/schema_object.rb +5 -8
- data/lib/rails/graphql/type/object/type_object.rb +62 -25
- data/lib/rails/graphql/type/object.rb +34 -26
- data/lib/rails/graphql/type/scalar/any_scalar.rb +30 -0
- data/lib/rails/graphql/type/scalar/bigint_scalar.rb +5 -5
- data/lib/rails/graphql/type/scalar/binary_scalar.rb +5 -3
- data/lib/rails/graphql/type/scalar/boolean_scalar.rb +8 -8
- data/lib/rails/graphql/type/scalar/date_scalar.rb +5 -3
- data/lib/rails/graphql/type/scalar/date_time_scalar.rb +5 -3
- data/lib/rails/graphql/type/scalar/decimal_scalar.rb +5 -3
- data/lib/rails/graphql/type/scalar/float_scalar.rb +5 -5
- data/lib/rails/graphql/type/scalar/id_scalar.rb +6 -5
- data/lib/rails/graphql/type/scalar/int_scalar.rb +6 -5
- data/lib/rails/graphql/type/scalar/json_scalar.rb +41 -0
- data/lib/rails/graphql/type/scalar/string_scalar.rb +18 -4
- data/lib/rails/graphql/type/scalar/time_scalar.rb +8 -6
- data/lib/rails/graphql/type/scalar.rb +26 -23
- data/lib/rails/graphql/type/union.rb +21 -18
- data/lib/rails/graphql/type.rb +43 -26
- data/lib/rails/graphql/type_map.rb +268 -165
- data/lib/rails/graphql/uri.rb +167 -0
- data/lib/rails/graphql/version.rb +19 -3
- data/lib/rails/graphql.rake +3 -0
- data/lib/rails/graphql.rb +91 -56
- data/lib/rails-graphql.rb +1 -1
- data/test/assets/en.yml +29 -0
- data/test/assets/introspection-mem.txt +1 -1
- data/test/assets/introspection.gql +2 -0
- data/test/assets/mem.gql +86 -99
- data/test/assets/mysql.gql +406 -0
- data/test/assets/sqlite.gql +96 -73
- data/test/assets/translate.gql +346 -0
- data/test/config.rb +19 -8
- data/test/graphql/schema_test.rb +14 -50
- data/test/graphql/source_test.rb +8 -85
- data/test/graphql/type/enum_test.rb +207 -203
- data/test/graphql/type/input_test.rb +14 -9
- data/test/graphql/type/interface_test.rb +12 -9
- data/test/graphql/type/object_test.rb +8 -2
- data/test/graphql/type/scalar/any_scalar_test.rb +38 -0
- data/test/graphql/type/scalar/boolean_scalar_test.rb +6 -3
- data/test/graphql/type/scalar/json_scalar_test.rb +23 -0
- data/test/graphql/type_map_test.rb +63 -81
- data/test/graphql/type_test.rb +0 -19
- data/test/graphql_test.rb +1 -1
- data/test/integration/{authorization/authorization_test.rb → authorization_test.rb} +40 -14
- data/test/integration/config.rb +36 -3
- data/test/integration/customization_test.rb +39 -0
- data/test/integration/global_id_test.rb +99 -0
- data/test/integration/memory/star_wars_introspection_test.rb +24 -16
- data/test/integration/memory/star_wars_query_test.rb +54 -3
- data/test/integration/memory/star_wars_validation_test.rb +3 -3
- data/test/integration/mysql/star_wars_introspection_test.rb +25 -0
- data/test/integration/persisted_query_test.rb +87 -0
- data/test/integration/resolver_precedence_test.rb +154 -0
- data/test/integration/schemas/memory.rb +24 -10
- data/test/integration/schemas/mysql.rb +62 -0
- data/test/integration/schemas/sqlite.rb +21 -12
- data/test/integration/sqlite/star_wars_global_id_test.rb +89 -0
- data/test/integration/sqlite/star_wars_introspection_test.rb +10 -0
- data/test/integration/sqlite/star_wars_query_test.rb +14 -1
- data/test/integration/translate_test.rb +73 -0
- data/test/test_ext.rb +16 -13
- metadata +125 -161
- data/ext/depend +0 -3
- data/ext/graphqlparser/Ast.cpp +0 -346
- data/ext/graphqlparser/Ast.h +0 -1214
- data/ext/graphqlparser/AstNode.h +0 -36
- data/ext/graphqlparser/AstVisitor.h +0 -137
- data/ext/graphqlparser/GraphQLParser.cpp +0 -76
- data/ext/graphqlparser/GraphQLParser.h +0 -55
- data/ext/graphqlparser/JsonVisitor.cpp +0 -161
- data/ext/graphqlparser/JsonVisitor.cpp.inc +0 -456
- data/ext/graphqlparser/JsonVisitor.h +0 -121
- data/ext/graphqlparser/JsonVisitor.h.inc +0 -110
- data/ext/graphqlparser/VERSION +0 -1
- data/ext/graphqlparser/c/GraphQLAst.cpp +0 -324
- data/ext/graphqlparser/c/GraphQLAst.h +0 -180
- data/ext/graphqlparser/c/GraphQLAstForEachConcreteType.h +0 -44
- data/ext/graphqlparser/c/GraphQLAstNode.cpp +0 -25
- data/ext/graphqlparser/c/GraphQLAstNode.h +0 -33
- data/ext/graphqlparser/c/GraphQLAstToJSON.cpp +0 -21
- data/ext/graphqlparser/c/GraphQLAstToJSON.h +0 -24
- data/ext/graphqlparser/c/GraphQLAstVisitor.cpp +0 -55
- data/ext/graphqlparser/c/GraphQLAstVisitor.h +0 -53
- data/ext/graphqlparser/c/GraphQLParser.cpp +0 -35
- data/ext/graphqlparser/c/GraphQLParser.h +0 -54
- data/ext/graphqlparser/dump_json_ast.cpp +0 -48
- data/ext/graphqlparser/lexer.lpp +0 -324
- data/ext/graphqlparser/parser.ypp +0 -693
- data/ext/graphqlparser/parsergen/lexer.cpp +0 -2633
- data/ext/graphqlparser/parsergen/lexer.h +0 -528
- data/ext/graphqlparser/parsergen/location.hh +0 -189
- data/ext/graphqlparser/parsergen/parser.tab.cpp +0 -3300
- data/ext/graphqlparser/parsergen/parser.tab.hpp +0 -646
- data/ext/graphqlparser/parsergen/position.hh +0 -179
- data/ext/graphqlparser/parsergen/stack.hh +0 -156
- data/ext/graphqlparser/syntaxdefs.h +0 -19
- data/ext/libgraphqlparser/AstNode.h +0 -36
- data/ext/libgraphqlparser/CMakeLists.txt +0 -148
- data/ext/libgraphqlparser/CONTRIBUTING.md +0 -23
- data/ext/libgraphqlparser/GraphQLParser.cpp +0 -76
- data/ext/libgraphqlparser/GraphQLParser.h +0 -55
- data/ext/libgraphqlparser/JsonVisitor.cpp +0 -161
- data/ext/libgraphqlparser/JsonVisitor.h +0 -121
- data/ext/libgraphqlparser/LICENSE +0 -22
- data/ext/libgraphqlparser/README.clang-tidy +0 -7
- data/ext/libgraphqlparser/README.md +0 -84
- data/ext/libgraphqlparser/ast/ast.ast +0 -203
- data/ext/libgraphqlparser/ast/ast.py +0 -61
- data/ext/libgraphqlparser/ast/c.py +0 -100
- data/ext/libgraphqlparser/ast/c.pyc +0 -0
- data/ext/libgraphqlparser/ast/c_impl.py +0 -61
- data/ext/libgraphqlparser/ast/c_impl.pyc +0 -0
- data/ext/libgraphqlparser/ast/c_visitor_impl.py +0 -39
- data/ext/libgraphqlparser/ast/c_visitor_impl.pyc +0 -0
- data/ext/libgraphqlparser/ast/casing.py +0 -26
- data/ext/libgraphqlparser/ast/casing.pyc +0 -0
- data/ext/libgraphqlparser/ast/cxx.py +0 -197
- data/ext/libgraphqlparser/ast/cxx.pyc +0 -0
- data/ext/libgraphqlparser/ast/cxx_impl.py +0 -61
- data/ext/libgraphqlparser/ast/cxx_impl.pyc +0 -0
- data/ext/libgraphqlparser/ast/cxx_json_visitor_header.py +0 -42
- data/ext/libgraphqlparser/ast/cxx_json_visitor_header.pyc +0 -0
- data/ext/libgraphqlparser/ast/cxx_json_visitor_impl.py +0 -80
- data/ext/libgraphqlparser/ast/cxx_json_visitor_impl.pyc +0 -0
- data/ext/libgraphqlparser/ast/cxx_visitor.py +0 -64
- data/ext/libgraphqlparser/ast/cxx_visitor.pyc +0 -0
- data/ext/libgraphqlparser/ast/js.py +0 -65
- data/ext/libgraphqlparser/ast/license.py +0 -10
- data/ext/libgraphqlparser/ast/license.pyc +0 -0
- data/ext/libgraphqlparser/c/GraphQLAstNode.cpp +0 -25
- data/ext/libgraphqlparser/c/GraphQLAstNode.h +0 -33
- data/ext/libgraphqlparser/c/GraphQLAstToJSON.cpp +0 -21
- data/ext/libgraphqlparser/c/GraphQLAstToJSON.h +0 -24
- data/ext/libgraphqlparser/c/GraphQLAstVisitor.cpp +0 -55
- data/ext/libgraphqlparser/c/GraphQLAstVisitor.h +0 -53
- data/ext/libgraphqlparser/c/GraphQLParser.cpp +0 -35
- data/ext/libgraphqlparser/c/GraphQLParser.h +0 -54
- data/ext/libgraphqlparser/clang-tidy-all.sh +0 -3
- data/ext/libgraphqlparser/cmake/version.cmake +0 -16
- data/ext/libgraphqlparser/dump_json_ast.cpp +0 -48
- data/ext/libgraphqlparser/go/README.md +0 -20
- data/ext/libgraphqlparser/go/callbacks.go +0 -18
- data/ext/libgraphqlparser/go/gotest.go +0 -64
- data/ext/libgraphqlparser/lexer.lpp +0 -324
- data/ext/libgraphqlparser/libgraphqlparser.pc.in +0 -11
- data/ext/libgraphqlparser/parser.ypp +0 -693
- data/ext/libgraphqlparser/parsergen/lexer.cpp +0 -2633
- data/ext/libgraphqlparser/parsergen/lexer.h +0 -528
- data/ext/libgraphqlparser/parsergen/location.hh +0 -189
- data/ext/libgraphqlparser/parsergen/parser.tab.cpp +0 -3300
- data/ext/libgraphqlparser/parsergen/parser.tab.hpp +0 -646
- data/ext/libgraphqlparser/parsergen/position.hh +0 -179
- data/ext/libgraphqlparser/parsergen/stack.hh +0 -156
- data/ext/libgraphqlparser/python/CMakeLists.txt +0 -14
- data/ext/libgraphqlparser/python/README.md +0 -5
- data/ext/libgraphqlparser/python/example.py +0 -31
- data/ext/libgraphqlparser/syntaxdefs.h +0 -19
- data/ext/libgraphqlparser/test/BuildCAPI.c +0 -5
- data/ext/libgraphqlparser/test/CMakeLists.txt +0 -25
- data/ext/libgraphqlparser/test/JsonVisitorTests.cpp +0 -28
- data/ext/libgraphqlparser/test/ParserTests.cpp +0 -352
- data/ext/libgraphqlparser/test/kitchen-sink.graphql +0 -59
- data/ext/libgraphqlparser/test/kitchen-sink.json +0 -1
- data/ext/libgraphqlparser/test/schema-kitchen-sink.graphql +0 -78
- data/ext/libgraphqlparser/test/schema-kitchen-sink.json +0 -1
- data/ext/libgraphqlparser/test/valgrind.supp +0 -33
- data/ext/version.cpp +0 -21
- data/lib/graphqlparser.so +0 -0
- data/lib/rails/graphql/native/functions.rb +0 -38
- data/lib/rails/graphql/native/location.rb +0 -41
- data/lib/rails/graphql/native/pointers.rb +0 -23
- data/lib/rails/graphql/native/visitor.rb +0 -349
- data/lib/rails/graphql/native.rb +0 -56
- data/test/integration/schemas/authorization.rb +0 -12
@@ -1,7 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
module Rails
|
4
|
-
module GraphQL
|
3
|
+
module Rails
|
4
|
+
module GraphQL
|
5
5
|
# = GraphQL Request
|
6
6
|
#
|
7
7
|
# This class is responsible for processing a GraphQL response. It will
|
@@ -11,19 +11,38 @@ module Rails # :nodoc:
|
|
11
11
|
#
|
12
12
|
# ==== Options
|
13
13
|
#
|
14
|
+
# * <tt>:args</tt> - The arguments of the request, same as variables
|
15
|
+
# * <tt>:as</tt> - The format of the output of the request, supports both
|
16
|
+
# +:hash+ and +:string+ (defaults to :string)
|
17
|
+
# * <tt>:context</tt> - The context of the request, which can be accessed in
|
18
|
+
# fields, resolvers and so as a way to customize the result
|
19
|
+
# * <tt>:controller</tt> - From which controller this operation is running
|
20
|
+
# from, which provides view-like access to helpers and methods through the
|
21
|
+
# request
|
14
22
|
# * <tt>:namespace</tt> - Set what is the namespace used for the request
|
15
|
-
# (defaults to :base)
|
23
|
+
# (defaults to :base)
|
24
|
+
# * <tt>:operation_name</tt> - The name of the operation as a sort of label,
|
25
|
+
# it can also be collected by the name of the single operation in the
|
26
|
+
# request
|
27
|
+
# * <tt>:schema</tt> - The schema on which the request should run on. It
|
28
|
+
# has higher precedence than the namespace
|
29
|
+
# * <tt>:variables</tt> - The variables of the request
|
16
30
|
class Request
|
17
31
|
extend ActiveSupport::Autoload
|
18
32
|
|
19
|
-
RESPONSE_FORMATS = {
|
33
|
+
RESPONSE_FORMATS = {
|
34
|
+
string: :to_json,
|
35
|
+
object: :as_json,
|
36
|
+
json: :as_json,
|
37
|
+
hash: :as_json,
|
38
|
+
}.freeze
|
20
39
|
|
21
40
|
eager_autoload do
|
22
41
|
autoload_under :steps do
|
23
42
|
autoload :Authorizable
|
24
43
|
autoload :Organizable
|
25
|
-
autoload :
|
26
|
-
autoload :
|
44
|
+
autoload :Preparable
|
45
|
+
autoload :Resolvable
|
27
46
|
end
|
28
47
|
|
29
48
|
autoload_under :helpers do
|
@@ -33,15 +52,28 @@ module Rails # :nodoc:
|
|
33
52
|
end
|
34
53
|
|
35
54
|
autoload :Arguments
|
55
|
+
autoload :Backtrace
|
36
56
|
autoload :Component
|
37
57
|
autoload :Context
|
38
58
|
autoload :Errors
|
39
59
|
autoload :Event
|
60
|
+
autoload :PreparedData
|
40
61
|
autoload :Strategy
|
62
|
+
autoload :Subscription
|
41
63
|
end
|
42
64
|
|
43
|
-
attr_reader :
|
44
|
-
:
|
65
|
+
attr_reader :args, :origin, :errors, :fragments, :operations, :response, :schema,
|
66
|
+
:stack, :strategy, :document, :operation_name, :subscriptions
|
67
|
+
|
68
|
+
alias arguments args
|
69
|
+
alias controller origin
|
70
|
+
alias channel origin
|
71
|
+
|
72
|
+
delegate :action_name, to: :controller, allow_nil: true
|
73
|
+
delegate :find_type!, to: :strategy, allow_nil: true
|
74
|
+
delegate :all_listeners, :all_events, to: :schema
|
75
|
+
|
76
|
+
alias find_type find_type!
|
45
77
|
|
46
78
|
class << self
|
47
79
|
# Shortcut for initialize, set context, and execute
|
@@ -51,6 +83,16 @@ module Rails # :nodoc:
|
|
51
83
|
result.execute(*args, **xargs)
|
52
84
|
end
|
53
85
|
|
86
|
+
# Shortcut for initialize and compile
|
87
|
+
def compile(*args, schema: nil, namespace: :base, **xargs)
|
88
|
+
new(schema, namespace: namespace).compile(*args, **xargs)
|
89
|
+
end
|
90
|
+
|
91
|
+
# Shortcut for initialize and validate
|
92
|
+
def valid?(*args, schema: nil, namespace: :base, **xargs)
|
93
|
+
new(schema, namespace: namespace).valid?(*args, **xargs)
|
94
|
+
end
|
95
|
+
|
54
96
|
# Allow accessing component-based objects through the request
|
55
97
|
def const_defined?(name, *)
|
56
98
|
Component.const_defined?(name) || super
|
@@ -60,32 +102,19 @@ module Rails # :nodoc:
|
|
60
102
|
def const_missing(name)
|
61
103
|
Component.const_defined?(name) ? Component.const_get(name) : super
|
62
104
|
end
|
63
|
-
|
64
|
-
def eager_load! # :nodoc:
|
65
|
-
super
|
66
|
-
|
67
|
-
Request::Component.eager_load!
|
68
|
-
Request::Strategy.eager_load!
|
69
|
-
end
|
70
105
|
end
|
71
106
|
|
72
107
|
# Forces the schema to be registered on type map before moving forward
|
73
108
|
def initialize(schema = nil, namespace: :base)
|
74
109
|
@namespace = schema&.namespace || namespace
|
75
110
|
@schema = GraphQL::Schema.find!(@namespace)
|
76
|
-
@extensions = {}
|
77
111
|
|
78
112
|
ensure_schema!
|
79
113
|
end
|
80
114
|
|
81
|
-
#
|
82
|
-
def
|
83
|
-
@
|
84
|
-
end
|
85
|
-
|
86
|
-
# Cache all the schema events for this current request
|
87
|
-
def all_events
|
88
|
-
@all_events ||= schema.all_events
|
115
|
+
# Check if any new subscription was added
|
116
|
+
def subscriptions?
|
117
|
+
defined?(@subscriptions) && @subscriptions.any?
|
89
118
|
end
|
90
119
|
|
91
120
|
# Get the context of the request
|
@@ -98,19 +127,103 @@ module Rails # :nodoc:
|
|
98
127
|
@context = build_ostruct(data).freeze
|
99
128
|
end
|
100
129
|
|
130
|
+
# Allow adding extra information to the response, in a extensions key
|
131
|
+
def extensions
|
132
|
+
@extensions ||= {}
|
133
|
+
end
|
134
|
+
|
101
135
|
# Execute a given document with the given arguments
|
102
|
-
def execute(document,
|
136
|
+
def execute(document, **xargs)
|
137
|
+
output = xargs.delete(:as) || schema.config.default_response_format
|
138
|
+
cache = xargs.delete(:hash)
|
139
|
+
formatter = RESPONSE_FORMATS[output]
|
140
|
+
|
141
|
+
document, cache = nil, document if xargs.delete(:compiled)
|
142
|
+
prepared_data = xargs.delete(:data_for)
|
103
143
|
reset!(**xargs)
|
104
144
|
|
105
|
-
|
106
|
-
|
145
|
+
@response = initialize_response(output, formatter)
|
146
|
+
import_prepared_data(prepared_data)
|
147
|
+
execute!(document, cache)
|
107
148
|
|
108
|
-
|
109
|
-
|
149
|
+
response.public_send(formatter)
|
150
|
+
rescue StaticResponse
|
151
|
+
# TODO: Maybe change this to a throw/catch instead
|
152
|
+
response.public_send(formatter)
|
110
153
|
end
|
111
154
|
|
112
155
|
alias perform execute
|
113
156
|
|
157
|
+
# Compile a given document
|
158
|
+
def compile(document, compress: true)
|
159
|
+
reset!
|
160
|
+
|
161
|
+
log_execution(document, event: 'compile.graphql') do
|
162
|
+
@document = initialize_document(document)
|
163
|
+
run_document(with: :compile)
|
164
|
+
|
165
|
+
result = Marshal.dump(cache_dump)
|
166
|
+
result = Zlib.deflate(result) if compress
|
167
|
+
|
168
|
+
@log_extra[:total] = result.bytesize
|
169
|
+
result
|
170
|
+
end
|
171
|
+
end
|
172
|
+
|
173
|
+
# Check if the given document is valid by piggybacking on the compile
|
174
|
+
# process
|
175
|
+
def valid?(document)
|
176
|
+
reset!
|
177
|
+
|
178
|
+
log_execution(document, event: 'validate.graphql') do
|
179
|
+
@document = initialize_document(document)
|
180
|
+
run_document(with: :compile)
|
181
|
+
@log_extra[:result] = @errors.empty?
|
182
|
+
end
|
183
|
+
end
|
184
|
+
|
185
|
+
# This is used by cache and static responses to jump from executing to
|
186
|
+
# delivery a response right away
|
187
|
+
def force_response(response, error = StaticResponse)
|
188
|
+
return unless defined?(@response)
|
189
|
+
@response = response
|
190
|
+
raise error
|
191
|
+
end
|
192
|
+
|
193
|
+
# Import prepared data that is formatted as a hash
|
194
|
+
def import_prepared_data(prepared_data)
|
195
|
+
prepared_data&.each do |key, value|
|
196
|
+
prepare_data_for(key, value)
|
197
|
+
end
|
198
|
+
end
|
199
|
+
|
200
|
+
# Add a new prepared data from +value+ to the given +field+
|
201
|
+
def prepare_data_for(field, value, **options)
|
202
|
+
field = PreparedData.lookup(self, field)
|
203
|
+
|
204
|
+
if prepared_data.key?(field)
|
205
|
+
prepared_data[field].push(value)
|
206
|
+
else
|
207
|
+
prepared_data[field] = PreparedData.new(field, value, **options)
|
208
|
+
end
|
209
|
+
end
|
210
|
+
|
211
|
+
# Recover the next prepared data for the given field
|
212
|
+
def prepared_data_for(field)
|
213
|
+
return unless defined?(@prepared_data)
|
214
|
+
|
215
|
+
field = field.field if field.is_a?(Component::Field)
|
216
|
+
prepared_data[field]
|
217
|
+
end
|
218
|
+
|
219
|
+
# Check if the given field has prepared data
|
220
|
+
def prepared_data_for?(field)
|
221
|
+
return false unless defined?(@prepared_data)
|
222
|
+
|
223
|
+
field = field.field if field.is_a?(Component::Field)
|
224
|
+
prepared_data.key?(field)
|
225
|
+
end
|
226
|
+
|
114
227
|
# Build a easy-to-access object representing the current information of
|
115
228
|
# the execution to be used on +rescue_with_handler+
|
116
229
|
def build_rescue_object(**extra)
|
@@ -125,7 +238,8 @@ module Rails # :nodoc:
|
|
125
238
|
|
126
239
|
# Use schema handlers for exceptions caught during the execution process
|
127
240
|
def rescue_with_handler(exception, **extra)
|
128
|
-
|
241
|
+
ExtendedError.extend(exception, build_rescue_object(**extra))
|
242
|
+
schema.rescue_with_handler(exception)
|
129
243
|
end
|
130
244
|
|
131
245
|
# Add the given +exception+ to the errors using the +node+ location
|
@@ -136,17 +250,27 @@ module Rails # :nodoc:
|
|
136
250
|
|
137
251
|
# A little helper to report an error on a given node
|
138
252
|
def report_node_error(message, node, **xargs)
|
253
|
+
xargs[:locations] ||= location_of(node)
|
254
|
+
report_error(message, **xargs)
|
255
|
+
end
|
256
|
+
|
257
|
+
# Get the location object of a given node
|
258
|
+
def location_of(node)
|
139
259
|
node = node.instance_variable_get(:@node) if node.is_a?(Request::Component)
|
140
|
-
|
260
|
+
return unless node.is_a?(GQLParser::Token)
|
141
261
|
|
142
|
-
|
143
|
-
|
262
|
+
[
|
263
|
+
{ 'line' => node.begin_line, 'column' => node.begin_column },
|
264
|
+
{ 'line' => node.end_line, 'column' => node.end_column },
|
265
|
+
]
|
144
266
|
end
|
145
267
|
|
146
268
|
# The final helper that facilitates how errors are reported
|
147
269
|
def report_error(message, **xargs)
|
148
270
|
xargs[:path] ||= stack_to_path
|
149
271
|
errors.add(message, **xargs)
|
272
|
+
|
273
|
+
nil # Return nil for easier usage
|
150
274
|
end
|
151
275
|
|
152
276
|
# Add the given +object+ into the execution +stack+ and execute the given
|
@@ -154,8 +278,6 @@ module Rails # :nodoc:
|
|
154
278
|
def stacked(object, &block)
|
155
279
|
stack.unshift(object)
|
156
280
|
block.call
|
157
|
-
rescue => exception
|
158
|
-
rescue_with_handler(exception) || raise
|
159
281
|
ensure
|
160
282
|
stack.shift
|
161
283
|
end
|
@@ -167,28 +289,28 @@ module Rails # :nodoc:
|
|
167
289
|
end.compact.reverse
|
168
290
|
end
|
169
291
|
|
170
|
-
# Add extensions to the request, which ensures a bunch of
|
171
|
-
# behaviors for all the objects created through the request
|
292
|
+
# Add class extensions to the request, which ensures a bunch of
|
293
|
+
# extended behaviors for all the objects created through the request
|
172
294
|
def extend(*modules)
|
173
|
-
|
174
|
-
request_ext =
|
295
|
+
import_class_extensions(*modules)
|
296
|
+
request_ext = class_extensions[self.class]
|
175
297
|
super(request_ext) if request_ext && !is_a?(request_ext)
|
176
298
|
end
|
177
299
|
|
178
|
-
# This initiates a new object which is aware of extensions
|
300
|
+
# This initiates a new object which is aware of class extensions
|
179
301
|
def build(klass, *args, &block)
|
180
|
-
ext_module =
|
302
|
+
ext_module = class_extensions[klass]
|
181
303
|
obj = klass.new(*args, &block)
|
182
304
|
obj.extend(ext_module) if ext_module
|
183
305
|
obj
|
184
306
|
end
|
185
307
|
|
186
|
-
#
|
187
|
-
def
|
188
|
-
|
189
|
-
|
190
|
-
|
191
|
-
|
308
|
+
# This allocates a new object which is aware of class extensions
|
309
|
+
def build_from_cache(klass)
|
310
|
+
ext_module = class_extensions[klass]
|
311
|
+
obj = klass.allocate
|
312
|
+
obj.extend(ext_module) if ext_module
|
313
|
+
obj
|
192
314
|
end
|
193
315
|
|
194
316
|
# A shared way to cache information across the execution of an request
|
@@ -196,59 +318,148 @@ module Rails # :nodoc:
|
|
196
318
|
@cache[key] ||= (init_value || block&.call || {})
|
197
319
|
end
|
198
320
|
|
199
|
-
|
321
|
+
# A better way to ensure that nil values in a hash cache won't be
|
322
|
+
# reinitialized
|
323
|
+
def nested_cache(key, sub_key)
|
324
|
+
(source = cache(key)).key?(sub_key) ? source[sub_key] : source[sub_key] = yield
|
325
|
+
end
|
326
|
+
|
327
|
+
# Show if the current cached operation is still valid
|
328
|
+
def valid_cache?
|
329
|
+
defined?(@valid_cache) && @valid_cache
|
330
|
+
end
|
331
|
+
|
332
|
+
# Write the request into the cache so it can run again faster
|
333
|
+
def write_cache_request(hash, data = cache_dump)
|
334
|
+
schema.write_on_cache(hash, Marshal.dump(data))
|
335
|
+
end
|
336
|
+
|
337
|
+
# Read the request from the cache to run it faster
|
338
|
+
def read_cache_request(data = @document)
|
339
|
+
begin
|
340
|
+
data = Zlib.inflate(data) if data[0] == 'x'
|
341
|
+
data = Marshal.load(data)
|
342
|
+
rescue Zlib::BufError, ArgumentError
|
343
|
+
raise ::ArgumentError, +'Unable to recover the cached request.'
|
344
|
+
end
|
200
345
|
|
201
|
-
|
346
|
+
cache_load(data)
|
347
|
+
end
|
348
|
+
|
349
|
+
# Build the object that represent the request in the cache format
|
350
|
+
def cache_dump
|
351
|
+
{
|
352
|
+
strategy: @strategy.cache_dump,
|
353
|
+
operation_name: @operation_name,
|
354
|
+
type_map_version: schema.version,
|
355
|
+
document: @document,
|
356
|
+
errors: @errors.cache_dump,
|
357
|
+
operations: @operations.transform_values(&:cache_dump),
|
358
|
+
fragments: @fragments&.transform_values { |f| f.try(:cache_dump) }&.compact,
|
359
|
+
}
|
360
|
+
end
|
361
|
+
|
362
|
+
# Read the request from the cache to run it faster
|
363
|
+
def cache_load(data)
|
364
|
+
version = data[:type_map_version]
|
365
|
+
@document = data[:document]
|
366
|
+
@operation_name = data[:operation_name]
|
367
|
+
resolve_from_cache = (version == schema.version)
|
368
|
+
|
369
|
+
# Run the document from scratch if TypeMap has changed
|
370
|
+
# TODO: We need to save the new organized document
|
371
|
+
return run_document unless resolve_from_cache
|
372
|
+
@valid_cache = true unless defined?(@valid_cache)
|
373
|
+
|
374
|
+
# Run the document as a cached operation
|
375
|
+
errors.cache_load(data[:errors])
|
376
|
+
@strategy = build(data[:strategy][:class], self)
|
377
|
+
@strategy.trigger_event(:request)
|
378
|
+
@strategy.cache_load(data)
|
379
|
+
@strategy.resolve!
|
380
|
+
end
|
381
|
+
|
382
|
+
protected
|
383
|
+
|
384
|
+
# Stores all the class extensions
|
385
|
+
def class_extensions
|
386
|
+
@class_extensions ||= {}
|
387
|
+
end
|
388
|
+
|
389
|
+
# Stores all the prepared data, but only when it is needed
|
390
|
+
def prepared_data
|
391
|
+
@prepared_data ||= {}
|
392
|
+
end
|
393
|
+
|
394
|
+
private
|
202
395
|
|
203
396
|
# Reset principal variables and set the given +args+
|
204
|
-
def reset!(args: nil, variables: {}, operation_name: nil)
|
205
|
-
@
|
206
|
-
|
207
|
-
@
|
397
|
+
def reset!(args: nil, variables: {}, operation_name: nil, origin: nil)
|
398
|
+
@arg_names = {}
|
399
|
+
|
400
|
+
@args = (args || variables || {}).transform_keys do |key|
|
401
|
+
key.to_s.camelize(:lower).tap do |sanitized_key|
|
402
|
+
@arg_names[sanitized_key] = key
|
403
|
+
end
|
404
|
+
end
|
405
|
+
|
406
|
+
@args = build_ostruct(@args).freeze
|
407
|
+
@errors = Request::Errors.new(self)
|
208
408
|
@operation_name = operation_name
|
409
|
+
@origin = origin
|
209
410
|
|
210
411
|
@stack = [schema]
|
211
412
|
@cache = {}
|
212
|
-
@
|
213
|
-
@
|
413
|
+
@log_extra = {}
|
414
|
+
@subscriptions = {}
|
415
|
+
@used_variables = Set.new
|
416
|
+
|
417
|
+
@strategy = nil
|
418
|
+
schema.validate
|
214
419
|
end
|
215
420
|
|
216
421
|
# This executes the whole process capturing any exceptions and handling
|
217
422
|
# them as defined by the schema
|
218
|
-
def execute!(document)
|
219
|
-
log_execution(document) do
|
220
|
-
@document =
|
221
|
-
|
222
|
-
|
223
|
-
@strategy = find_strategy!
|
224
|
-
@strategy.trigger_event(:request)
|
225
|
-
@strategy.resolve!
|
423
|
+
def execute!(document, cache = nil)
|
424
|
+
log_execution(document, cache) do
|
425
|
+
@document = initialize_document(document, cache)
|
426
|
+
@document.is_a?(String) ? read_cache_request : run_document
|
226
427
|
end
|
227
|
-
rescue ParseError => err
|
228
|
-
parts = err.message.match(/\A(\d+)\.(\d+)(?:-\d+)?: (.*)\z/)
|
229
|
-
errors.add(parts[3], line: parts[1], col: parts[2])
|
230
428
|
ensure
|
429
|
+
report_unused_variables
|
430
|
+
write_cache_request(cache) if cache.present? && !valid_cache?
|
431
|
+
@response.try(:append_errors, errors)
|
432
|
+
|
433
|
+
if defined?(@extensions)
|
434
|
+
@response.try(:append_extensions, @extensions)
|
435
|
+
@extensions.clear
|
436
|
+
end
|
437
|
+
|
231
438
|
@cache.clear
|
232
|
-
@
|
233
|
-
@
|
439
|
+
@strategy&.clear
|
440
|
+
@fragments&.clear
|
441
|
+
@operations&.clear
|
442
|
+
@prepared_data&.clear
|
443
|
+
end
|
234
444
|
|
235
|
-
|
236
|
-
|
445
|
+
# Prepare the definitions, find the strategy and resolve
|
446
|
+
def run_document(with: :resolve!)
|
447
|
+
return if @document.nil?
|
237
448
|
|
238
|
-
|
239
|
-
@
|
449
|
+
collect_definitions!
|
450
|
+
@strategy ||= find_strategy!
|
451
|
+
@strategy.trigger_event(:request) if with == :resolve!
|
452
|
+
@strategy.public_send(with)
|
240
453
|
end
|
241
454
|
|
242
|
-
#
|
455
|
+
# Organize the list of definitions from the document
|
243
456
|
def collect_definitions!
|
244
|
-
|
245
|
-
|
246
|
-
|
247
|
-
|
248
|
-
|
249
|
-
|
250
|
-
end
|
251
|
-
end
|
457
|
+
@operations = @document[0]&.index_by { |node| node[1] }
|
458
|
+
@fragments = @document[1]&.index_by { |node| node[0] }
|
459
|
+
|
460
|
+
raise ::ArgumentError, (+<<~MSG).squish if operations.blank?
|
461
|
+
The document does not contains operations.
|
462
|
+
MSG
|
252
463
|
end
|
253
464
|
|
254
465
|
# Find the best strategy to resolve the request
|
@@ -259,9 +470,9 @@ module Rails # :nodoc:
|
|
259
470
|
build(klass, self)
|
260
471
|
end
|
261
472
|
|
262
|
-
# Find all necessary extensions inside the given +modules+
|
263
|
-
# the extension base module
|
264
|
-
def
|
473
|
+
# Find all necessary class extensions inside the given +modules+
|
474
|
+
# and prepare the extension base module
|
475
|
+
def import_class_extensions(*modules)
|
265
476
|
modules.each do |mod|
|
266
477
|
mod.constants.each do |const_name|
|
267
478
|
const_name = const_name.to_s
|
@@ -275,47 +486,75 @@ module Rails # :nodoc:
|
|
275
486
|
end
|
276
487
|
end
|
277
488
|
|
278
|
-
# Create the shared module and include the extension
|
489
|
+
# Create the shared module and include the class extension
|
279
490
|
next unless klass&.is_a?(Class)
|
280
|
-
|
281
|
-
|
491
|
+
class_extensions[klass] ||= Module.new
|
492
|
+
class_extensions[klass].include(const)
|
282
493
|
end
|
283
494
|
end
|
284
495
|
end
|
285
496
|
|
286
497
|
# Log the execution of a GraphQL document
|
287
|
-
def log_execution(document)
|
288
|
-
|
289
|
-
|
498
|
+
def log_execution(document, hash = nil, event: 'request.graphql')
|
499
|
+
return yield if event.nil?
|
500
|
+
|
501
|
+
data = { document: document, hash: hash }
|
502
|
+
ActiveSupport::Notifications.instrument(event, **data) do |payload|
|
503
|
+
yield.tap { log_payload(payload) }
|
290
504
|
end
|
291
505
|
end
|
292
506
|
|
293
507
|
# Build the payload to be sent to the log
|
294
|
-
def log_payload(
|
508
|
+
def log_payload(data)
|
295
509
|
name = @operation_name.presence
|
296
|
-
name ||= operations.keys.first if operations
|
297
|
-
map_variables = args.to_h
|
510
|
+
name ||= operations.keys.first if operations&.size&.eql?(1)
|
511
|
+
map_variables = args.to_h.transform_keys do |key|
|
512
|
+
@arg_names[key.to_s]
|
513
|
+
end
|
298
514
|
|
515
|
+
data.merge!(@log_extra)
|
299
516
|
data.merge!(
|
300
517
|
name: name,
|
301
518
|
cached: false,
|
302
|
-
|
303
|
-
variables: map_variables,
|
519
|
+
variables: map_variables.presence,
|
304
520
|
)
|
305
521
|
end
|
306
522
|
|
307
|
-
#
|
523
|
+
# When document is empty and the hash has been provided, then
|
524
|
+
def initialize_document(document, cache = nil)
|
525
|
+
if document.present?
|
526
|
+
::GQLParser.parse_execution(document)
|
527
|
+
elsif cache.nil?
|
528
|
+
raise ::ArgumentError, +'Unable to execute an empty document.'
|
529
|
+
elsif schema.cached?(cache)
|
530
|
+
schema.read_from_cache(cache)
|
531
|
+
else
|
532
|
+
@valid_cache = true
|
533
|
+
cache
|
534
|
+
end
|
535
|
+
rescue ::GQLParser::ParserError => err
|
536
|
+
parts = err.message.match(/\A(Parser error: .*) at \[(\d+), (\d+)\]\z/m)
|
537
|
+
errors.add(parts[1], line: parts[2].to_i, col: parts[3].to_i)
|
538
|
+
nil
|
539
|
+
end
|
540
|
+
|
541
|
+
# Initialize the class that responsible for storing the response
|
308
542
|
def initialize_response(as_format, to)
|
309
|
-
raise ::ArgumentError,
|
310
|
-
The given format #{as_format.inspect} is not a valid
|
543
|
+
raise ::ArgumentError, (+<<~MSG).squish if to.nil?
|
544
|
+
The given format #{as_format.inspect} is not a valid response format.
|
311
545
|
MSG
|
312
546
|
|
313
|
-
klass =
|
314
|
-
|
315
|
-
|
547
|
+
klass =
|
548
|
+
if schema.config.enable_string_collector && as_format == :string
|
549
|
+
Collectors::JsonCollector
|
550
|
+
elsif RESPONSE_FORMATS.key?(as_format)
|
551
|
+
Collectors::HashCollector
|
552
|
+
else
|
553
|
+
as_format
|
554
|
+
end
|
316
555
|
|
317
556
|
obj = klass.new(self)
|
318
|
-
raise ::ArgumentError,
|
557
|
+
raise ::ArgumentError, (+<<~MSG).squish unless obj.respond_to?(to)
|
319
558
|
Unable to use "#{klass.name}" as response collector since it does
|
320
559
|
not implement a #{to.inspect} method.
|
321
560
|
MSG
|
@@ -326,7 +565,7 @@ module Rails # :nodoc:
|
|
326
565
|
# Little helper to build an +OpenStruct+ ensure the given +value+ is a
|
327
566
|
# +Hash+. It can also +transform_keys+ with the given block
|
328
567
|
def build_ostruct(value, &block)
|
329
|
-
raise ::ArgumentError,
|
568
|
+
raise ::ArgumentError, (+<<~MSG).squish unless value.is_a?(::Hash)
|
330
569
|
The "#{value.class.name}" is not a valid hash.
|
331
570
|
MSG
|
332
571
|
|
@@ -337,11 +576,21 @@ module Rails # :nodoc:
|
|
337
576
|
# Make sure that a schema was assigned by find the corresponding one for
|
338
577
|
# the namespace of the request
|
339
578
|
def ensure_schema!
|
340
|
-
raise ::ArgumentError,
|
579
|
+
raise ::ArgumentError, (+<<~MSG).squish if schema.nil?
|
341
580
|
Unable to perform a request under the #{@namespace.inspect} namespace,
|
342
581
|
because there are no schema assigned to it.
|
343
582
|
MSG
|
344
583
|
end
|
584
|
+
|
585
|
+
# Check all the operations and report any provided variable that was not
|
586
|
+
# used
|
587
|
+
def report_unused_variables
|
588
|
+
(@arg_names.keys - @used_variables.to_a).each do |key|
|
589
|
+
errors.add((+<<~MSG).squish)
|
590
|
+
Variable $#{@arg_names[key]} was provided but not used.
|
591
|
+
MSG
|
592
|
+
end
|
593
|
+
end
|
345
594
|
end
|
346
595
|
end
|
347
596
|
end
|