rails-graphql 0.2.1 → 1.0.0.beta
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 +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 +646 -0
- data/ext/shared.c +482 -0
- data/ext/shared.h +177 -0
- 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 +36 -0
- data/lib/rails/graphql/alternative/mutation.rb +17 -0
- data/lib/rails/graphql/alternative/query.rb +93 -0
- data/lib/rails/graphql/alternative/subscription.rb +17 -0
- data/lib/rails/graphql/alternative.rb +20 -0
- data/lib/rails/graphql/argument.rb +21 -24
- data/lib/rails/graphql/callback.rb +24 -9
- data/lib/rails/graphql/collectors/hash_collector.rb +14 -6
- data/lib/rails/graphql/collectors/idented_collector.rb +10 -7
- data/lib/rails/graphql/collectors/json_collector.rb +22 -17
- data/lib/rails/graphql/collectors.rb +4 -4
- data/lib/rails/graphql/config.rb +130 -15
- 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 +5 -4
- data/lib/rails/graphql/directive/skip_directive.rb +5 -4
- data/lib/rails/graphql/directive.rb +118 -63
- data/lib/rails/graphql/errors.rb +33 -4
- data/lib/rails/graphql/event.rb +16 -5
- data/lib/rails/graphql/field/authorized_field.rb +19 -3
- data/lib/rails/graphql/field/input_field.rb +11 -10
- data/lib/rails/graphql/field/mutation_field.rb +42 -7
- data/lib/rails/graphql/field/output_field.rb +102 -13
- data/lib/rails/graphql/field/proxied_field.rb +31 -22
- data/lib/rails/graphql/field/resolved_field.rb +26 -24
- data/lib/rails/graphql/field/scoped_config.rb +10 -4
- data/lib/rails/graphql/field/subscription_field.rb +140 -0
- data/lib/rails/graphql/field/typed_field.rb +43 -22
- data/lib/rails/graphql/field.rb +70 -56
- data/lib/rails/graphql/global_id.rb +85 -0
- data/lib/rails/graphql/helpers/attribute_delegator.rb +5 -5
- data/lib/rails/graphql/helpers/inherited_collection/array.rb +50 -0
- data/lib/rails/graphql/helpers/inherited_collection/base.rb +43 -0
- data/lib/rails/graphql/helpers/inherited_collection/hash.rb +87 -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 +31 -27
- data/lib/rails/graphql/helpers/with_assignment.rb +6 -6
- data/lib/rails/graphql/helpers/with_callbacks.rb +25 -8
- data/lib/rails/graphql/helpers/with_description.rb +71 -0
- data/lib/rails/graphql/helpers/with_directives.rb +54 -30
- data/lib/rails/graphql/helpers/with_events.rb +21 -23
- data/lib/rails/graphql/helpers/with_fields.rb +76 -22
- data/lib/rails/graphql/helpers/with_global_id.rb +22 -0
- data/lib/rails/graphql/helpers/with_name.rb +43 -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 +137 -55
- 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 +88 -33
- data/lib/rails/graphql/railties/base_generator.rb +3 -9
- data/lib/rails/graphql/railties/channel.rb +157 -0
- data/lib/rails/graphql/railties/controller.rb +62 -17
- 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 +24 -49
- data/lib/rails/graphql/request/backtrace.rb +191 -0
- data/lib/rails/graphql/request/component/field.rb +86 -65
- data/lib/rails/graphql/request/component/fragment.rb +72 -24
- data/lib/rails/graphql/request/component/operation/subscription.rb +164 -4
- data/lib/rails/graphql/request/component/operation.rb +63 -31
- data/lib/rails/graphql/request/component/spread.rb +68 -25
- data/lib/rails/graphql/request/component/typename.rb +27 -12
- data/lib/rails/graphql/request/component.rb +75 -36
- data/lib/rails/graphql/request/context.rb +18 -8
- data/lib/rails/graphql/request/errors.rb +16 -6
- data/lib/rails/graphql/request/event.rb +19 -8
- data/lib/rails/graphql/request/helpers/directives.rb +68 -27
- data/lib/rails/graphql/request/helpers/selection_set.rb +51 -25
- data/lib/rails/graphql/request/helpers/value_writers.rb +18 -16
- data/lib/rails/graphql/request/prepared_data.rb +98 -0
- data/lib/rails/graphql/request/steps/authorizable.rb +24 -14
- data/lib/rails/graphql/request/steps/organizable.rb +110 -48
- data/lib/rails/graphql/request/steps/{prepareable.rb → preparable.rb} +20 -7
- data/lib/rails/graphql/request/steps/{resolveable.rb → resolvable.rb} +15 -6
- 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 +131 -75
- data/lib/rails/graphql/request/subscription.rb +80 -0
- data/lib/rails/graphql/request.rb +305 -86
- data/lib/rails/graphql/schema.rb +240 -48
- data/lib/rails/graphql/shortcuts.rb +22 -3
- data/lib/rails/graphql/source/active_record/builders.rb +49 -35
- data/lib/rails/graphql/source/active_record_source.rb +70 -54
- data/lib/rails/graphql/source/base.rb +111 -0
- data/lib/rails/graphql/source/builder.rb +128 -0
- data/lib/rails/graphql/source/scoped_arguments.rb +31 -19
- data/lib/rails/graphql/source.rb +89 -213
- data/lib/rails/graphql/subscription/provider/action_cable.rb +112 -0
- data/lib/rails/graphql/subscription/provider/base.rb +191 -0
- data/lib/rails/graphql/subscription/provider.rb +18 -0
- data/lib/rails/graphql/subscription/store/base.rb +145 -0
- data/lib/rails/graphql/subscription/store/memory.rb +127 -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/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 +34 -48
- data/lib/rails/graphql/type/input.rb +74 -23
- data/lib/rails/graphql/type/interface.rb +16 -26
- data/lib/rails/graphql/type/object/directive_object.rb +4 -4
- 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 +3 -3
- data/lib/rails/graphql/type/object/schema_object.rb +5 -8
- data/lib/rails/graphql/type/object/type_object.rb +29 -19
- data/lib/rails/graphql/type/object.rb +26 -23
- 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 +3 -3
- data/lib/rails/graphql/type/scalar/boolean_scalar.rb +8 -8
- data/lib/rails/graphql/type/scalar/date_scalar.rb +3 -3
- data/lib/rails/graphql/type/scalar/date_time_scalar.rb +3 -3
- data/lib/rails/graphql/type/scalar/decimal_scalar.rb +3 -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 +39 -0
- data/lib/rails/graphql/type/scalar/string_scalar.rb +18 -4
- data/lib/rails/graphql/type/scalar/time_scalar.rb +5 -5
- data/lib/rails/graphql/type/scalar.rb +25 -22
- data/lib/rails/graphql/type/union.rb +14 -16
- data/lib/rails/graphql/type.rb +34 -25
- data/lib/rails/graphql/type_map.rb +256 -164
- data/lib/rails/graphql/uri.rb +166 -0
- data/lib/rails/graphql/version.rb +15 -3
- data/lib/rails/graphql.rake +3 -0
- data/lib/rails/graphql.rb +85 -52
- 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/mem.gql +18 -45
- data/test/assets/mysql.gql +392 -0
- data/test/assets/sqlite.gql +21 -12
- data/test/assets/translate.gql +335 -0
- data/test/config.rb +18 -8
- data/test/graphql/schema_test.rb +12 -19
- data/test/graphql/source_test.rb +8 -75
- 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 +4 -4
- 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 +51 -66
- 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 +1 -1
- 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 +22 -7
- 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 +83 -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 +61 -0
- data/test/test_ext.rb +16 -13
- metadata +108 -157
- 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
data/lib/rails/graphql/schema.rb
CHANGED
@@ -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 Schema
|
6
6
|
#
|
7
7
|
# This is a pure representation of a GraphQL schema.
|
@@ -11,7 +11,7 @@ module Rails # :nodoc:
|
|
11
11
|
# namespaces, where each schema is associated with one and only one
|
12
12
|
# namespace, guiding requests and types searching.
|
13
13
|
#
|
14
|
-
# This class works
|
14
|
+
# This class works similarly to the {TypeMap}[rdoc-ref:Rails::base_classMap]
|
15
15
|
# class, where its purpose is to know which QueryFields, Mutations, and
|
16
16
|
# Subscriptions are available. The main difference is that it doesn't hold
|
17
17
|
# namespace-based objects, since each schema is associated to a single
|
@@ -19,17 +19,13 @@ module Rails # :nodoc:
|
|
19
19
|
class Schema
|
20
20
|
extend Helpers::WithSchemaFields
|
21
21
|
extend Helpers::WithDirectives
|
22
|
+
extend Helpers::WithGlobalID
|
22
23
|
extend Helpers::Registerable
|
23
24
|
extend GraphQL::Introspection
|
24
25
|
|
25
26
|
include ActiveSupport::Configurable
|
26
27
|
include ActiveSupport::Rescuable
|
27
|
-
|
28
|
-
# The purpose of instantiating an schema is to have access to its
|
29
|
-
# public methods. It then runs from the strategy perspective, pointing
|
30
|
-
# out any other methods to the manually set event
|
31
|
-
delegate_missing_to :event
|
32
|
-
attr_reader :event
|
28
|
+
include Helpers::Instantiable
|
33
29
|
|
34
30
|
self.abstract = true
|
35
31
|
self.spec_object = true
|
@@ -37,20 +33,26 @@ module Rails # :nodoc:
|
|
37
33
|
|
38
34
|
# Imports schema specific configurations
|
39
35
|
configure do |config|
|
40
|
-
%i[
|
41
|
-
|
36
|
+
inherited_keys = %i[
|
37
|
+
enable_introspection request_strategies
|
38
|
+
enable_string_collector default_response_format
|
39
|
+
schema_type_names cache
|
40
|
+
default_subscription_provider default_subscription_broadcastable
|
41
|
+
].to_set
|
42
|
+
|
43
|
+
config.default_proc = proc do |hash, key|
|
44
|
+
hash[key] = GraphQL.config.send(key) if inherited_keys.include?(key)
|
42
45
|
end
|
43
46
|
end
|
44
47
|
|
48
|
+
rescue_from(PersistedQueryNotFound) do |error|
|
49
|
+
response = { errors: [{ message: +'PersistedQueryNotFound' }] }
|
50
|
+
error.request.force_response(response, error)
|
51
|
+
end
|
52
|
+
|
45
53
|
class << self
|
46
54
|
delegate :type_map, :logger, to: '::Rails::GraphQL'
|
47
|
-
|
48
|
-
# Mark the given class to be pending of registration
|
49
|
-
def inherited(subclass)
|
50
|
-
subclass.spec_object = false
|
51
|
-
subclass.abstract = false
|
52
|
-
super if defined? super
|
53
|
-
end
|
55
|
+
delegate :version, to: :type_map
|
54
56
|
|
55
57
|
# :singleton-method:
|
56
58
|
# Since there are only one schema per namespace, the name is constant
|
@@ -63,7 +65,7 @@ module Rails # :nodoc:
|
|
63
65
|
# :singleton-method:
|
64
66
|
# Since there is only one schema per namespace, then both kind and
|
65
67
|
# to_sym, which is used to register, are the same
|
66
|
-
def kind
|
68
|
+
def kind
|
67
69
|
:schema
|
68
70
|
end
|
69
71
|
|
@@ -90,9 +92,18 @@ module Rails # :nodoc:
|
|
90
92
|
end
|
91
93
|
|
92
94
|
# :singleton-method:
|
93
|
-
#
|
94
|
-
def
|
95
|
-
|
95
|
+
# The base class of all schemas is always +Schema+
|
96
|
+
def gid_base_class
|
97
|
+
Schema
|
98
|
+
end
|
99
|
+
|
100
|
+
# :singleton-method:
|
101
|
+
# Return the schema
|
102
|
+
def find_by_gid(gid)
|
103
|
+
result = find!(gid.namespace.to_sym)
|
104
|
+
return result if gid.name.nil?
|
105
|
+
|
106
|
+
result.find_field!(gid.scope, gid.name)
|
96
107
|
end
|
97
108
|
|
98
109
|
# Find all types that are available for the current schema
|
@@ -100,17 +111,66 @@ module Rails # :nodoc:
|
|
100
111
|
type_map.each_from(namespace, base_class: base_class, &block)
|
101
112
|
end
|
102
113
|
|
103
|
-
# Schemas are assigned to a single namespace
|
104
|
-
|
105
|
-
|
114
|
+
# Schemas are assigned to a single namespace. You can provide a module
|
115
|
+
# as the second argument to associate that module to the same namespace
|
116
|
+
def set_namespace(ns, mod = nil)
|
117
|
+
@namespace = normalize_namespaces([ns]).first
|
118
|
+
type_map.associate(@namespace, mod) if mod.is_a?(Module)
|
106
119
|
end
|
107
120
|
|
121
|
+
alias set_namespaces set_namespace
|
122
|
+
|
108
123
|
# Schemas are assigned to a single namespace and not inherited
|
109
|
-
def namespace(*
|
110
|
-
|
124
|
+
def namespace(*args)
|
125
|
+
if args.present?
|
126
|
+
set_namespace(*args)
|
127
|
+
elsif defined?(@namespace) && !@namespace.nil?
|
128
|
+
@namespace
|
129
|
+
else
|
130
|
+
:base
|
131
|
+
end
|
132
|
+
end
|
133
|
+
|
134
|
+
# Add compatibility to the list of namespaces
|
135
|
+
def namespaces
|
136
|
+
namespace
|
137
|
+
end
|
138
|
+
|
139
|
+
# Return the subscription provider for the current schema
|
140
|
+
def subscription_provider
|
141
|
+
if !defined?(@subscription_provider)
|
142
|
+
@subscription_provider = config.default_subscription_provider
|
143
|
+
subscription_provider
|
144
|
+
elsif @subscription_provider.is_a?(String)
|
145
|
+
provider = (name = @subscription_provider).safe_constantize
|
146
|
+
return @subscription_provider = provider.new(logger: logger) unless provider.nil?
|
147
|
+
|
148
|
+
raise ::NameError, +"uninitialized constant #{name}"
|
149
|
+
else
|
150
|
+
@subscription_provider
|
151
|
+
end
|
111
152
|
end
|
112
153
|
|
113
|
-
# Check if the
|
154
|
+
# Check if the schema is valid
|
155
|
+
def valid?
|
156
|
+
defined?(@validated) && @validated
|
157
|
+
end
|
158
|
+
|
159
|
+
# Only run the validated process if it has not yet been validated
|
160
|
+
def validate
|
161
|
+
validate! unless valid?
|
162
|
+
rescue StandardError
|
163
|
+
GraphQL.logger.warn(+"\e[1m\e[31mSchema #{name} is invalid!\e[0m")
|
164
|
+
raise
|
165
|
+
end
|
166
|
+
|
167
|
+
# Run validations and then mark itself as validated
|
168
|
+
def validate!(*)
|
169
|
+
super if defined? super
|
170
|
+
@validated = true
|
171
|
+
end
|
172
|
+
|
173
|
+
# Check if the class is already registered in the type map
|
114
174
|
def registered?
|
115
175
|
type_map.object_exist?(self, exclusive: true)
|
116
176
|
end
|
@@ -118,11 +178,7 @@ module Rails # :nodoc:
|
|
118
178
|
# The process to register a class and it's name on the index
|
119
179
|
def register!
|
120
180
|
return if self == GraphQL::Schema
|
121
|
-
|
122
|
-
unless registered?
|
123
|
-
super if defined? super
|
124
|
-
return type_map.register(self).method(:validate!)
|
125
|
-
end
|
181
|
+
return super unless registered?
|
126
182
|
|
127
183
|
current = type_map.fetch(:schema,
|
128
184
|
namespaces: namespace,
|
@@ -130,15 +186,16 @@ module Rails # :nodoc:
|
|
130
186
|
exclusive: true,
|
131
187
|
)
|
132
188
|
|
133
|
-
raise ArgumentError,
|
189
|
+
raise ArgumentError, (+<<~MSG).squish
|
134
190
|
The #{namespace.inspect} namespace is already assigned to "#{current.name}".
|
135
191
|
Please change the namespace for "#{klass.name}" class.
|
136
192
|
MSG
|
137
193
|
end
|
138
194
|
|
139
|
-
#
|
140
|
-
def
|
141
|
-
|
195
|
+
# Hook into the unregister process to reset the subscription provider
|
196
|
+
def unregister!
|
197
|
+
restart_subscriptions
|
198
|
+
super
|
142
199
|
end
|
143
200
|
|
144
201
|
# Find a given +type+ associated with the schema
|
@@ -164,6 +221,65 @@ module Rails # :nodoc:
|
|
164
221
|
type_map.fetch!(directive, **xargs)
|
165
222
|
end
|
166
223
|
|
224
|
+
# Remove subscriptions by their provided +sids+
|
225
|
+
def remove_subscriptions(*sids)
|
226
|
+
subscription_provider&.remove(*sids)
|
227
|
+
end
|
228
|
+
|
229
|
+
# Add a new subscription using all the provided request subscription
|
230
|
+
# objects
|
231
|
+
def add_subscriptions(*subscriptions)
|
232
|
+
subscription_provider.add(*subscriptions)
|
233
|
+
end
|
234
|
+
|
235
|
+
# The the schema is unloaded, we need to make sure that the provider
|
236
|
+
# can smoothly shutdown itself
|
237
|
+
def restart_subscriptions
|
238
|
+
return unless defined?(@subscription_provider) && !@subscription_provider.nil?
|
239
|
+
subscription_provider.shutdown
|
240
|
+
end
|
241
|
+
|
242
|
+
# Checks if the given +operation+ can be subscribed to
|
243
|
+
def accepts_subscription?(operation)
|
244
|
+
subscription_provider.accepts?(operation)
|
245
|
+
end
|
246
|
+
|
247
|
+
# This receives a request subscription object and return an id for that.
|
248
|
+
# By default, it just produces a random uuid
|
249
|
+
def subscription_id_for(*)
|
250
|
+
SecureRandom.uuid
|
251
|
+
end
|
252
|
+
|
253
|
+
# Simple delegator to the cache store set on the schema config, mapped
|
254
|
+
# to +exist?+
|
255
|
+
def cached?(name, options = nil)
|
256
|
+
config.cache.exist?(expand_cache_key(name), options)
|
257
|
+
end
|
258
|
+
|
259
|
+
# Simple delegator to the cache store set on the schema config, mapped
|
260
|
+
# to +delete+
|
261
|
+
def delete_from_cache(name, options = nil)
|
262
|
+
config.cache.delete(expand_cache_key(name), options)
|
263
|
+
end
|
264
|
+
|
265
|
+
# Simple delegator to the cache store set on the schema config, mapped
|
266
|
+
# to +read+
|
267
|
+
def read_from_cache(name, options = nil)
|
268
|
+
config.cache.read(expand_cache_key(name), options)
|
269
|
+
end
|
270
|
+
|
271
|
+
# Simple delegator to the cache store set on the schema config, mapped
|
272
|
+
# to +write+
|
273
|
+
def write_on_cache(name, value, options = nil)
|
274
|
+
config.cache.write(expand_cache_key(name), value, options)
|
275
|
+
end
|
276
|
+
|
277
|
+
# Simple delegator to the cache store set on the schema config, mapped
|
278
|
+
# to +fetch+
|
279
|
+
def fetch_from_cache(name, options = nil)
|
280
|
+
config.cache.fetch(expand_cache_key(name), options)
|
281
|
+
end
|
282
|
+
|
167
283
|
# Describe a schema as a GraphQL string
|
168
284
|
def to_gql(**xargs)
|
169
285
|
ToGQL.describe(self, **xargs)
|
@@ -171,12 +287,84 @@ module Rails # :nodoc:
|
|
171
287
|
|
172
288
|
protected
|
173
289
|
|
174
|
-
|
290
|
+
attr_writer :subscription_provider
|
291
|
+
|
292
|
+
# Mark the given class to be pending of registration
|
293
|
+
def inherited(subclass)
|
294
|
+
subclass.spec_object = false
|
295
|
+
subclass.abstract = false
|
296
|
+
super if defined? super
|
297
|
+
|
298
|
+
# The only way to actually get the namespace into the cache prefix
|
299
|
+
subclass.config.define_singleton_method(:cache_prefix) do
|
300
|
+
self[:cache_prefix] ||= "#{GraphQL.config.cache_prefix}#{subclass.namespace}/"
|
301
|
+
end
|
302
|
+
end
|
303
|
+
|
304
|
+
# Indicate to type map that the current schema depends on all the
|
305
|
+
# files in the provided +path+ directory
|
306
|
+
def load_directory(dir = '.', recursive: true)
|
307
|
+
source = caller_locations(2, 1).first.path
|
308
|
+
|
309
|
+
absolute = dir.start_with?(File::SEPARATOR)
|
310
|
+
path = recursive ? File.join('**', '*.rb') : '*.rb'
|
311
|
+
dir = File.expand_path(dir, File.dirname(source)) unless absolute
|
312
|
+
|
313
|
+
list = Dir.glob(File.join(dir, path)).select do |file_name|
|
314
|
+
file_name != source
|
315
|
+
end
|
316
|
+
|
317
|
+
type_map.add_dependencies(list, to: namespace)
|
318
|
+
end
|
319
|
+
|
320
|
+
alias load_current_directory load_directory
|
321
|
+
|
322
|
+
# Load a list of known dependencies based on the given +type+
|
323
|
+
def load_dependencies(type, *list)
|
324
|
+
GraphQL.add_dependencies(type, *list, to: namespace)
|
325
|
+
end
|
326
|
+
|
327
|
+
# A syntax sugar for +load_dependencies(:directive, *list)+
|
328
|
+
def load_directives(*list)
|
329
|
+
load_dependencies(:directive, *list)
|
330
|
+
end
|
331
|
+
|
332
|
+
# A syntax sugar for +load_dependencies(:source, *list)+
|
333
|
+
def load_sources(*list, build: false)
|
334
|
+
load_dependencies(:source, *list)
|
335
|
+
build_all_sources if build
|
336
|
+
end
|
337
|
+
|
338
|
+
# Build all sources that has the belongs to the current namespace
|
339
|
+
def build_all_sources
|
340
|
+
GraphQL::Source.descendants.each do |klass|
|
341
|
+
next if klass.abstract?
|
342
|
+
|
343
|
+
ns = klass.namespaces
|
344
|
+
klass.build_all if (ns.blank? && namespace == :base) ||
|
345
|
+
ns == namespace || ns.try(:include?, namespace)
|
346
|
+
end
|
347
|
+
end
|
348
|
+
|
349
|
+
# Make sure to prefix the cache key
|
350
|
+
def expand_cache_key(name)
|
351
|
+
if name.is_a?(String)
|
352
|
+
name = +"#{config.cache_prefix}#{name}"
|
353
|
+
elsif name.respond_to?(:cache_key=)
|
354
|
+
name.cache_key = +"#{config.cache_prefix}#{name.cache_key}"
|
355
|
+
end
|
356
|
+
|
357
|
+
name
|
358
|
+
end
|
175
359
|
|
176
360
|
# Generate the helper methods to easily create types within the
|
177
361
|
# definition of the schema
|
178
362
|
GraphQL::Type::KINDS.each do |kind|
|
179
363
|
class_eval <<-RUBY, __FILE__, __LINE__ + 1
|
364
|
+
def load_#{kind.underscore.pluralize}(*list)
|
365
|
+
load_dependencies(:#{kind.underscore}, *list)
|
366
|
+
end
|
367
|
+
|
180
368
|
def #{kind.underscore}(name, **xargs, &block)
|
181
369
|
create_type(name, :#{kind}, **xargs, &block)
|
182
370
|
end
|
@@ -184,11 +372,13 @@ module Rails # :nodoc:
|
|
184
372
|
end
|
185
373
|
|
186
374
|
# Helper method to create a single source
|
187
|
-
def source(object, superclass = nil, **xargs, &block)
|
375
|
+
def source(object, superclass = nil, build: true, **xargs, &block)
|
188
376
|
superclass ||= GraphQL::Source.find_for!(object)
|
189
377
|
|
190
378
|
xargs[:suffix] = 'Source'
|
379
|
+
create_and_build = build
|
191
380
|
schema_namespace = namespace
|
381
|
+
|
192
382
|
create_klass(object, superclass, GraphQL::Source, **xargs) do
|
193
383
|
set_namespace schema_namespace
|
194
384
|
|
@@ -198,16 +388,16 @@ module Rails # :nodoc:
|
|
198
388
|
end
|
199
389
|
|
200
390
|
instance_exec(&block) if block.present?
|
201
|
-
|
391
|
+
build_all if create_and_build
|
202
392
|
end
|
203
393
|
end
|
204
394
|
|
205
395
|
# Helper method to create multiple sources with the same type
|
206
|
-
def sources(*list, of_type: nil, &block)
|
396
|
+
def sources(*list, of_type: nil, build: true, &block)
|
207
397
|
list = list.flatten
|
208
398
|
|
209
399
|
of_type ||= GraphQL::Source.find_for!(list.first)
|
210
|
-
list.each { |object| source(object, of_type, &block) }
|
400
|
+
list.each { |object| source(object, of_type, build: build, &block) }
|
211
401
|
end
|
212
402
|
|
213
403
|
# A simpler way to create a new type object without having to create
|
@@ -235,20 +425,24 @@ module Rails # :nodoc:
|
|
235
425
|
|
236
426
|
klass_name = name.classify.demodulize
|
237
427
|
klass_name += xargs[:suffix] if xargs.key?(:suffix) &&
|
238
|
-
!klass_name.
|
428
|
+
!klass_name.end_with?(xargs[:suffix])
|
239
429
|
|
240
430
|
if base_module.const_defined?(klass_name)
|
241
431
|
klass = base_module.const_get(klass_name)
|
242
432
|
|
243
|
-
raise DuplicatedError,
|
433
|
+
raise DuplicatedError, (+<<~MSG).squish unless !xargs[:once] && klass < superclass
|
244
434
|
A constant named "#{klass_name}" already exists for the
|
245
435
|
"#{base_module.name}" module.
|
246
436
|
MSG
|
437
|
+
|
438
|
+
# This likely happened because the classes are being reloaded, so
|
439
|
+
# call inherited again as if the class has just been created
|
440
|
+
superclass.inherited(klass)
|
247
441
|
else
|
248
442
|
base_class ||= superclass.ancestors.find { |k| k.superclass === Class }
|
249
443
|
|
250
444
|
valid = superclass.is_a?(Module) && superclass < base_class
|
251
|
-
raise DefinitionError,
|
445
|
+
raise DefinitionError, (+<<~MSG).squish unless valid
|
252
446
|
The given "#{superclass}" superclass does not inherites from
|
253
447
|
#{base_class.name} class.
|
254
448
|
MSG
|
@@ -261,12 +455,10 @@ module Rails # :nodoc:
|
|
261
455
|
klass.is_a?(Helpers::WithAssignment)
|
262
456
|
|
263
457
|
klass.set_namespace(namespace)
|
264
|
-
klass.
|
458
|
+
klass.module_exec(&block) if block.present?
|
265
459
|
klass
|
266
460
|
end
|
267
461
|
end
|
268
462
|
end
|
269
|
-
|
270
|
-
ActiveSupport.run_load_hooks(:graphql, Schema)
|
271
463
|
end
|
272
464
|
end
|
@@ -4,13 +4,20 @@
|
|
4
4
|
module GraphQL
|
5
5
|
# List of constant shortcuts, as string to not trigger autoload
|
6
6
|
CONST_SHORTCUTS = {
|
7
|
+
CacheKey: '::Rails::GraphQL::CacheKey',
|
8
|
+
Channel: '::Rails::GraphQL::Channel',
|
7
9
|
Controller: '::Rails::GraphQL::Controller',
|
8
10
|
Directive: '::Rails::GraphQL::Directive',
|
9
11
|
Field: '::Rails::GraphQL::Field',
|
10
|
-
|
12
|
+
GlobalID: '::Rails::GraphQL::GlobalID',
|
11
13
|
Request: '::Rails::GraphQL::Request',
|
12
14
|
Schema: '::Rails::GraphQL::Schema',
|
13
15
|
Source: '::Rails::GraphQL::Source',
|
16
|
+
Type: '::Rails::GraphQL::Type',
|
17
|
+
|
18
|
+
Query: '::Rails::GraphQL::Alternative::Query',
|
19
|
+
Mutation: '::Rails::GraphQL::Alternative::Mutation',
|
20
|
+
Subscription: '::Rails::GraphQL::Alternative::Subscription',
|
14
21
|
|
15
22
|
Enum: '::Rails::GraphQL::Type::Enum',
|
16
23
|
Input: '::Rails::GraphQL::Type::Input',
|
@@ -22,6 +29,7 @@ module GraphQL
|
|
22
29
|
ProxyField: '::Rails::GraphQL::Field::ProxyField',
|
23
30
|
AssociationField: '::Rails::GraphQL::Field::AssociationField',
|
24
31
|
|
32
|
+
BaseSource: '::Rails::GraphQL::Source::BaseSource',
|
25
33
|
ActiveRecordSource: '::Rails::GraphQL::Source::ActiveRecordSource',
|
26
34
|
}.freeze
|
27
35
|
|
@@ -38,8 +46,9 @@ module GraphQL
|
|
38
46
|
DIRECTIVE_SHORTCUTS = %i[DeprecatedDirective IncludeDirective SkipDirective].freeze
|
39
47
|
|
40
48
|
class << self
|
41
|
-
delegate
|
42
|
-
delegate
|
49
|
+
delegate *DIRECTIVE_SHORTCUTS, to: 'Rails::GraphQL::Directive'
|
50
|
+
delegate :add_dependencies, :configure, :config, :to_gql, :to_graphql, :type_map,
|
51
|
+
to: 'Rails::GraphQL'
|
43
52
|
|
44
53
|
# See {Request}[rdoc-ref:Rails::GraphQL::Request]
|
45
54
|
def request(*args, **xargs)
|
@@ -53,6 +62,16 @@ module GraphQL
|
|
53
62
|
|
54
63
|
alias perform execute
|
55
64
|
|
65
|
+
# See {Request}[rdoc-ref:Rails::GraphQL::Request]
|
66
|
+
def compile(*args, **xargs)
|
67
|
+
Rails::GraphQL::Request.compile(*args, **xargs)
|
68
|
+
end
|
69
|
+
|
70
|
+
# See {Request}[rdoc-ref:Rails::GraphQL::Request]
|
71
|
+
def valid?(*args, **xargs)
|
72
|
+
Rails::GraphQL::Request.valid?(*args, **xargs)
|
73
|
+
end
|
74
|
+
|
56
75
|
# See {CONST_SHORTCUTS}[rdoc-ref:GraphQL::CONST_SHORTCUTS]
|
57
76
|
def const_defined?(name, *)
|
58
77
|
name = :"ActiveRecord#{name[2..-1]}" if name[0..1] === 'AR'
|
@@ -9,16 +9,17 @@ module Rails
|
|
9
9
|
sti_interface? ? interface_class : super
|
10
10
|
end
|
11
11
|
|
12
|
-
#
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
12
|
+
# List of all columns that should be threated as IDs
|
13
|
+
# TODO: Add a exclusive cache for the build process
|
14
|
+
def id_columns
|
15
|
+
@id_columns ||= begin
|
16
|
+
result = Set.new(GraphQL.enumerate(primary_key))
|
17
|
+
each_reflection.each_with_object(result) do |item, arr|
|
18
|
+
next unless item.belongs_to?
|
19
|
+
arr << item.foreign_key.to_s
|
20
|
+
arr << item.foreign_key if item.polymorphic?
|
21
|
+
end
|
19
22
|
end
|
20
|
-
|
21
|
-
items.compact.flatten.unshift(primary_key)
|
22
23
|
end
|
23
24
|
|
24
25
|
# Iterate over all the attributes, except the primary key, from the model
|
@@ -27,26 +28,32 @@ module Rails
|
|
27
28
|
def each_attribute(holder, skip_primary_key = true)
|
28
29
|
adapter_key = GraphQL.ar_adapter_key(adapter_name)
|
29
30
|
|
30
|
-
skip_fields =
|
31
|
+
skip_fields = Set.new
|
31
32
|
skip_fields << model.inheritance_column
|
32
33
|
skip_fields << primary_key unless skip_primary_key
|
33
34
|
|
34
|
-
send("#{adapter_key}_attributes") do |attribute, *args|
|
35
|
-
yield
|
35
|
+
send(:"#{adapter_key}_attributes") do |attribute, *args, **xargs|
|
36
|
+
yield(attribute, *args, **xargs) unless skip_fields.include?(attribute)
|
36
37
|
end
|
37
38
|
end
|
38
39
|
|
39
40
|
# Iterate over all the model reflections
|
40
|
-
|
41
|
-
|
42
|
-
skip_fields = skips_for(holder).map(&:to_s)
|
43
|
-
model._reflections.each_value do |reflection|
|
44
|
-
next if skip_fields.include?(reflection.name.to_s)
|
45
|
-
|
41
|
+
def each_reflection(&block)
|
42
|
+
model._reflections.each_value.select do |reflection|
|
46
43
|
reflection = model._reflections[reflection.to_s] \
|
47
44
|
unless reflection.is_a?(abstract_reflection)
|
48
45
|
|
49
|
-
|
46
|
+
!reflection.nil?
|
47
|
+
end.each(&block)
|
48
|
+
end
|
49
|
+
|
50
|
+
# Build arguments that correctly reflect the primary key, as a single
|
51
|
+
# column or as an array of columns
|
52
|
+
def build_primary_key_arguments(holder)
|
53
|
+
if primary_key.is_a?(::Array)
|
54
|
+
primary_key.each { |key| holder.argument(key, :id, null: false) }
|
55
|
+
else
|
56
|
+
holder.argument(primary_key, :id, null: false)
|
50
57
|
end
|
51
58
|
end
|
52
59
|
|
@@ -65,22 +72,22 @@ module Rails
|
|
65
72
|
def build_enum_types
|
66
73
|
return remove_instance_variable(:@enums) if enums.blank?
|
67
74
|
|
68
|
-
@enums = enums.
|
69
|
-
|
75
|
+
@enums = enums.each_with_object({}) do |(attribute, setting), hash|
|
76
|
+
class_name = base_name + attribute.to_s.classify
|
77
|
+
hash[attribute.to_s] = create_enum(class_name, setting, once: true)
|
70
78
|
rescue DuplicatedError
|
71
79
|
next
|
72
|
-
end.
|
80
|
+
end.freeze
|
73
81
|
end
|
74
82
|
|
75
83
|
# Build all necessary attribute fields into the given +holder+
|
76
84
|
def build_attribute_fields(holder, **field_options)
|
77
|
-
attributes_as_ids = reflection_attributes(holder)
|
78
85
|
each_attribute(holder) do |key, type, **options|
|
79
|
-
next if
|
86
|
+
next if holder.field?(key) || skip_field?(key, on: holder.kind)
|
80
87
|
|
81
88
|
str_key = key.to_s
|
82
89
|
type = (defined?(@enums) && @enums.key?(str_key) && @enums[str_key]) ||
|
83
|
-
(
|
90
|
+
(id_columns.include?(str_key) && :id) || type
|
84
91
|
|
85
92
|
options[:null] = !attr_required?(key) unless options.key?(:null)
|
86
93
|
holder.field(key, type, **options.merge(field_options[key] || {}))
|
@@ -89,15 +96,19 @@ module Rails
|
|
89
96
|
|
90
97
|
# Build all necessary reflection fields into the given +holder+
|
91
98
|
def build_reflection_fields(holder)
|
92
|
-
|
93
|
-
|
99
|
+
return unless with_associations?
|
100
|
+
|
101
|
+
each_reflection do |item|
|
102
|
+
next if holder.field?(item.name) || item.polymorphic? ||
|
103
|
+
skip_field?(item.name, on: holder.kind)
|
104
|
+
|
94
105
|
type_map_after_register(item.klass) do |type|
|
95
106
|
next unless (type.object? && type.try(:assigned_to) != item.klass) ||
|
96
107
|
type.interface?
|
97
108
|
|
98
109
|
options = reflection_to_options(item)
|
99
110
|
|
100
|
-
if type <= Source::
|
111
|
+
if type <= Source::Base
|
101
112
|
source_name = item.collection? ? type.plural : type.singular
|
102
113
|
proxy_options = options.merge(alias: reflection.name, of_type: :proxy)
|
103
114
|
|
@@ -106,21 +117,24 @@ module Rails
|
|
106
117
|
end
|
107
118
|
end
|
108
119
|
|
109
|
-
field ||= holder.
|
110
|
-
|
111
|
-
|
112
|
-
|
120
|
+
if (field ||= holder.safe_field(item.name, type, **options))
|
121
|
+
field.before_resolve(:preload_association, item.name)
|
122
|
+
field.before_resolve(:build_association_scope, item.name)
|
123
|
+
field.resolve(:parent_owned_records, item.collection?)
|
124
|
+
end
|
113
125
|
end
|
114
126
|
end
|
115
127
|
end
|
116
128
|
|
117
129
|
# Build all +accepts_nested_attributes_for+ inside the input object
|
118
130
|
def build_reflection_inputs(holder)
|
131
|
+
return unless with_associations?
|
132
|
+
|
119
133
|
model.nested_attributes_options.each_key do |reflection_name|
|
120
134
|
next if (reflection = model._reflect_on_association(reflection_name)).nil?
|
121
135
|
|
122
136
|
expected_name = reflection.klass.name.tr(':', '')
|
123
|
-
expected_name += 'Input' unless expected_name.
|
137
|
+
expected_name += 'Input' unless expected_name.end_with?('Input')
|
124
138
|
|
125
139
|
type_map_after_register(expected_name) do |input|
|
126
140
|
options = reflection_to_options(reflection).merge(null: true)
|
@@ -130,14 +144,14 @@ module Rails
|
|
130
144
|
end
|
131
145
|
end
|
132
146
|
|
133
|
-
# Transform a
|
147
|
+
# Transform a reflection into a field options
|
134
148
|
def reflection_to_options(reflection)
|
135
149
|
options = { array: reflection.collection? }
|
136
150
|
|
137
151
|
required = options[:array]
|
138
152
|
required ||= attr_required?(reflection.name)
|
139
153
|
required ||= attr_required?(reflection.association_foreign_key) \
|
140
|
-
if reflection.belongs_to?
|
154
|
+
if reflection.belongs_to? && !reflection.options[:optional]
|
141
155
|
|
142
156
|
options[:nullable] = !options[:array]
|
143
157
|
options[:null] = !required
|