rails-graphql 0.2.1 → 1.0.0.rc1
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 +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
|
# This is a helper module that basically works with fields that have an
|
6
6
|
# assigned type value
|
7
7
|
module Field::TypedField
|
@@ -13,14 +13,9 @@ module Rails # :nodoc:
|
|
13
13
|
|
14
14
|
delegate :input_type?, :output_type?, :leaf_type?, :kind, to: :type_klass
|
15
15
|
|
16
|
-
def initialize(name, type, *args, **xargs, &block)
|
17
|
-
|
18
|
-
|
19
|
-
@type = type.to_sym
|
20
|
-
else
|
21
|
-
@type = type.to_s.underscore.to_sym
|
22
|
-
end
|
23
|
-
|
16
|
+
def initialize(name, type = nil, *args, **xargs, &block)
|
17
|
+
type = (name == :id ? :id : :string) if type.nil?
|
18
|
+
assign_type(type)
|
24
19
|
super(name, *args, **xargs, &block)
|
25
20
|
end
|
26
21
|
|
@@ -32,11 +27,11 @@ module Rails # :nodoc:
|
|
32
27
|
|
33
28
|
# Check if types are compatible
|
34
29
|
def =~(other)
|
35
|
-
other.is_a?(Field::TypedField) && other.type_klass =~ type_klass
|
30
|
+
super && other.is_a?(Field::TypedField) && other.type_klass =~ type_klass
|
36
31
|
end
|
37
32
|
|
38
33
|
# Sometimes the owner does not designate this, but it is safe to assume it
|
39
|
-
# will be associated to the object
|
34
|
+
# will be associated to the object valid types
|
40
35
|
def valid_field_types
|
41
36
|
owner.try(:valid_field_types) || Type::Object.valid_field_types
|
42
37
|
end
|
@@ -55,29 +50,67 @@ module Rails # :nodoc:
|
|
55
50
|
)
|
56
51
|
end
|
57
52
|
|
53
|
+
alias type_class type_klass
|
54
|
+
|
58
55
|
# Add the listeners from the associated type
|
59
56
|
def all_listeners
|
60
|
-
|
57
|
+
inherited = super
|
58
|
+
return inherited unless type_klass.listeners?
|
59
|
+
inherited.present? ? inherited + type_klass.all_listeners : type_klass.all_listeners
|
60
|
+
end
|
61
|
+
|
62
|
+
# Make sure to check the associated type
|
63
|
+
def listeners?
|
64
|
+
super || type_klass.listeners?
|
61
65
|
end
|
62
66
|
|
63
67
|
# Add the events from the associated type
|
64
68
|
def all_events
|
65
|
-
|
69
|
+
inherited = super
|
70
|
+
return inherited unless type_klass.events?
|
71
|
+
return type_klass.all_events if inherited.blank?
|
72
|
+
Helpers.merge_hash_array(inherited, type_klass.all_events)
|
73
|
+
end
|
74
|
+
|
75
|
+
# Make sure to check the associated type
|
76
|
+
def events?
|
77
|
+
super || type_klass.events?
|
78
|
+
end
|
79
|
+
|
80
|
+
# Transforms the given value to its representation in a JSON string
|
81
|
+
def to_json(value)
|
82
|
+
return 'null' if value.nil?
|
83
|
+
return type_klass.to_json(value) unless array?
|
84
|
+
value.map { |part| type_klass.to_json(part) }
|
85
|
+
end
|
86
|
+
|
87
|
+
# Turn the given value into a JSON string representation
|
88
|
+
def as_json(value)
|
89
|
+
return if value.nil?
|
90
|
+
return type_klass.as_json(value) unless array?
|
91
|
+
value.map { |part| type_klass.as_json(part) }
|
92
|
+
end
|
93
|
+
|
94
|
+
# Turn a user input of this given type into an ruby object
|
95
|
+
def deserialize(value)
|
96
|
+
return if value.nil?
|
97
|
+
return type_klass.deserialize(value) unless array?
|
98
|
+
value.map { |val| type_klass.deserialize(val) unless val.nil? }
|
66
99
|
end
|
67
100
|
|
68
101
|
# Checks if the type of the field is valid
|
69
102
|
def validate!(*)
|
70
103
|
super if defined? super
|
71
104
|
|
72
|
-
raise ArgumentError,
|
73
|
-
Unable to find the "#{type.inspect}"
|
105
|
+
raise ArgumentError, (+<<~MSG).squish unless type_klass.is_a?(Module)
|
106
|
+
Unable to find the "#{type.inspect}" data type on GraphQL context.
|
74
107
|
MSG
|
75
108
|
|
76
109
|
valid_type = valid_field_types.empty? || valid_field_types.any? do |base_type|
|
77
110
|
type_klass < base_type
|
78
111
|
end
|
79
112
|
|
80
|
-
raise ArgumentError,
|
113
|
+
raise ArgumentError, (+<<~MSG).squish unless valid_type
|
81
114
|
The "#{type_klass.base_type}" is not accepted in this context.
|
82
115
|
MSG
|
83
116
|
end
|
@@ -86,16 +119,28 @@ module Rails # :nodoc:
|
|
86
119
|
|
87
120
|
# Little helper that shows the type of the field
|
88
121
|
def inspect_type
|
89
|
-
result = ': '
|
90
|
-
result
|
91
|
-
result
|
92
|
-
result
|
93
|
-
result
|
94
|
-
result
|
122
|
+
result = +': '
|
123
|
+
result << '[' if array?
|
124
|
+
result << type_klass.gql_name
|
125
|
+
result << '!' if array? && !nullable?
|
126
|
+
result << ']' if array?
|
127
|
+
result << '!' unless null?
|
95
128
|
result
|
96
129
|
end
|
97
130
|
|
98
|
-
|
131
|
+
# A little hidden helper to support forcing reassignment of type, which
|
132
|
+
# should only be done with caution
|
133
|
+
def assign_type(type)
|
134
|
+
if type.is_a?(Module) && type < GraphQL::Type
|
135
|
+
@type_klass = type
|
136
|
+
@type = type.to_sym
|
137
|
+
else
|
138
|
+
@type_klass = nil
|
139
|
+
@type = type
|
140
|
+
end
|
141
|
+
end
|
142
|
+
|
143
|
+
def proxied
|
99
144
|
super if defined? super
|
100
145
|
extend Field::TypedField::Proxied
|
101
146
|
end
|
data/lib/rails/graphql/field.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 Field
|
6
6
|
#
|
7
7
|
# A field has multiple purposes, which is defined by the specific subclass
|
@@ -20,11 +20,9 @@ module Rails # :nodoc:
|
|
20
20
|
# (defaults to true).
|
21
21
|
# * <tt>:full</tt> - Shortcut for +null: false, nullable: false, array: true+
|
22
22
|
# (defaults to false).
|
23
|
-
# * <tt>:method_name</tt> - The name of the method used to fetch the field data
|
24
|
-
# (defaults to nil).
|
25
23
|
# * <tt>:enabled</tt> - Mark the field as enabled
|
26
24
|
# (defaults to true).
|
27
|
-
# * <tt>:disabled</tt> - Works as the
|
25
|
+
# * <tt>:disabled</tt> - Works as the opposite of the enabled option
|
28
26
|
# (defaults to false).
|
29
27
|
# * <tt>:directives</tt> - The list of directives associated with the value
|
30
28
|
# (defaults to nil).
|
@@ -35,6 +33,7 @@ module Rails # :nodoc:
|
|
35
33
|
class Field
|
36
34
|
extend ActiveSupport::Autoload
|
37
35
|
include Helpers::WithDirectives
|
36
|
+
include Helpers::WithDescription
|
38
37
|
|
39
38
|
autoload :ScopedConfig
|
40
39
|
|
@@ -46,19 +45,25 @@ module Rails # :nodoc:
|
|
46
45
|
autoload :InputField
|
47
46
|
autoload :OutputField
|
48
47
|
autoload :MutationField
|
48
|
+
autoload :SubscriptionField
|
49
49
|
|
50
50
|
attr_reader :name, :gql_name, :owner
|
51
51
|
|
52
|
-
|
52
|
+
alias gid_base_class owner
|
53
|
+
alias proxied_owner owner
|
54
|
+
alias to_sym name
|
55
|
+
|
53
56
|
delegate :namespaces, to: :owner
|
57
|
+
delegate :input_type?, :output_type?, :leaf_type?, :proxy?,
|
58
|
+
:mutation?, :subscription?, to: :class
|
54
59
|
|
55
60
|
class << self
|
56
61
|
# A small shared helper method that allows field information to be
|
57
62
|
# proxied
|
58
63
|
def proxyable_methods(*list, klass:, allow_nil: false)
|
59
64
|
list = list.flatten.compact.map do |method_name|
|
60
|
-
ivar = '@' + method_name.delete_suffix('?')
|
61
|
-
accessor = 'field' + (allow_nil ? '&.' : '.') + method_name
|
65
|
+
ivar = +'@' + method_name.delete_suffix('?')
|
66
|
+
accessor = +'field' + (allow_nil ? '&.' : '.') + method_name
|
62
67
|
"def #{method_name}; defined?(#{ivar}) ? #{ivar} : #{accessor}; end"
|
63
68
|
end
|
64
69
|
|
@@ -89,13 +94,21 @@ module Rails # :nodoc:
|
|
89
94
|
def mutation?
|
90
95
|
false
|
91
96
|
end
|
97
|
+
|
98
|
+
# Checks if the field is associated with a subscription
|
99
|
+
def subscription?
|
100
|
+
false
|
101
|
+
end
|
92
102
|
end
|
93
103
|
|
94
104
|
def initialize(name, owner:, **xargs, &block)
|
95
105
|
@owner = owner
|
96
106
|
normalize_name(name)
|
97
107
|
|
98
|
-
|
108
|
+
# TODO: Replace by a proper method to build and set @directives
|
109
|
+
directives = GraphQL.directives_to_set(xargs[:directives], source: self)
|
110
|
+
@directives = directives unless directives.nil?
|
111
|
+
|
99
112
|
@method_name = xargs[:method_name].to_s.underscore.to_sym \
|
100
113
|
unless xargs[:method_name].nil?
|
101
114
|
|
@@ -104,13 +117,13 @@ module Rails # :nodoc:
|
|
104
117
|
@array = full ? true : xargs.fetch(:array, false)
|
105
118
|
@nullable = full ? false : xargs.fetch(:nullable, true)
|
106
119
|
|
107
|
-
|
120
|
+
self.description = xargs[:desc] || xargs[:description]
|
108
121
|
@enabled = xargs.fetch(:enabled, !xargs.fetch(:disabled, false))
|
109
122
|
|
110
123
|
configure(&block) if block.present?
|
111
124
|
end
|
112
125
|
|
113
|
-
def initialize_copy(*)
|
126
|
+
def initialize_copy(*)
|
114
127
|
super
|
115
128
|
|
116
129
|
@owner = nil
|
@@ -123,44 +136,69 @@ module Rails # :nodoc:
|
|
123
136
|
disable! if xargs.fetch(:disabled, false)
|
124
137
|
enable! if xargs.fetch(:enabled, false)
|
125
138
|
|
126
|
-
|
139
|
+
self.description = xargs[:desc] if xargs.key?(:desc)
|
140
|
+
self.description = xargs[:description] if xargs.key?(:description)
|
127
141
|
configure(&block) if block.present?
|
128
142
|
end
|
129
143
|
|
130
144
|
# Allow extra configurations to be performed using a block
|
131
145
|
def configure(&block)
|
132
146
|
Field::ScopedConfig.new(self, block.binding.receiver).instance_exec(&block)
|
147
|
+
self
|
148
|
+
end
|
149
|
+
|
150
|
+
# Return the owner as the single item of the list
|
151
|
+
def all_owners
|
152
|
+
[owner]
|
133
153
|
end
|
134
154
|
|
135
155
|
# Returns the name of the method used to retrieve the information
|
136
156
|
def method_name
|
137
|
-
defined?(@method_name)
|
157
|
+
if defined?(@method_name)
|
158
|
+
@method_name
|
159
|
+
elsif from_alternative?
|
160
|
+
:resolve
|
161
|
+
else
|
162
|
+
@name
|
163
|
+
end
|
138
164
|
end
|
139
165
|
|
140
|
-
#
|
141
|
-
def
|
142
|
-
|
143
|
-
other.array? == array? &&
|
144
|
-
(other.null? == null? || other.null? && !null?) &&
|
145
|
-
(other.nullable? == nullable? || other.nullable? && !nullable?)
|
166
|
+
# Mark the field as globally enabled
|
167
|
+
def enable!
|
168
|
+
@enabled = true
|
146
169
|
end
|
147
170
|
|
148
|
-
#
|
149
|
-
def
|
150
|
-
|
171
|
+
# Mark the field as globally disabled
|
172
|
+
def disable!
|
173
|
+
@enabled = false
|
151
174
|
end
|
152
175
|
|
153
|
-
#
|
176
|
+
# Update the null value
|
177
|
+
def required!
|
178
|
+
@null = false
|
179
|
+
end
|
180
|
+
|
181
|
+
# Update the nullable value
|
182
|
+
def required_items!
|
183
|
+
@nullable = false
|
184
|
+
end
|
185
|
+
|
186
|
+
# Checks if the field can be null
|
154
187
|
def null?
|
155
188
|
!!@null
|
156
189
|
end
|
157
190
|
|
158
|
-
# Checks if the
|
191
|
+
# Checks if the field cannot br null
|
192
|
+
def required?
|
193
|
+
!null?
|
194
|
+
end
|
195
|
+
|
196
|
+
# Checks if the field can be an array
|
159
197
|
def array?
|
160
198
|
!!@array
|
161
199
|
end
|
162
200
|
|
163
|
-
# Checks if the
|
201
|
+
# Checks if the field can have null elements in the array
|
164
202
|
def nullable?
|
165
203
|
!!@nullable
|
166
204
|
end
|
@@ -175,24 +213,9 @@ module Rails # :nodoc:
|
|
175
213
|
!enabled?
|
176
214
|
end
|
177
215
|
|
178
|
-
#
|
179
|
-
def
|
180
|
-
|
181
|
-
end
|
182
|
-
|
183
|
-
# Mark the field as globally disabled
|
184
|
-
def disable!
|
185
|
-
@enabled = false
|
186
|
-
end
|
187
|
-
|
188
|
-
# Return the description of the argument
|
189
|
-
def description
|
190
|
-
@desc
|
191
|
-
end
|
192
|
-
|
193
|
-
# Checks if a description was provided
|
194
|
-
def description?
|
195
|
-
defined?(@desc) && !!@desc
|
216
|
+
# Override to add the kind
|
217
|
+
def description(namespace = nil, *)
|
218
|
+
super(namespace, :field)
|
196
219
|
end
|
197
220
|
|
198
221
|
# Check if the field is an internal one
|
@@ -211,24 +234,18 @@ module Rails # :nodoc:
|
|
211
234
|
end
|
212
235
|
|
213
236
|
# Transforms the given value to its representation in a JSON string
|
214
|
-
def to_json(
|
215
|
-
|
216
|
-
return type_klass.to_json(value) unless array?
|
217
|
-
value.map { |part| type_klass.to_json(part) }
|
237
|
+
def to_json(*)
|
238
|
+
raise NotImplementedError, +"#{self.class.name} does not implement to_json"
|
218
239
|
end
|
219
240
|
|
220
241
|
# Turn the given value into a JSON string representation
|
221
|
-
def as_json(
|
222
|
-
|
223
|
-
return type_klass.as_json(value) unless array?
|
224
|
-
value.map { |part| type_klass.as_json(part) }
|
242
|
+
def as_json(*)
|
243
|
+
raise NotImplementedError, +"#{self.class.name} does not implement as_json"
|
225
244
|
end
|
226
245
|
|
227
246
|
# Turn a user input of this given type into an ruby object
|
228
|
-
def deserialize(
|
229
|
-
|
230
|
-
return type_klass.deserialize(value) unless array?
|
231
|
-
value.map { |val| type_klass.deserialize(val) unless val.nil? }
|
247
|
+
def deserialize(*)
|
248
|
+
raise NotImplementedError, +"#{self.class.name} does not implement deserialize"
|
232
249
|
end
|
233
250
|
|
234
251
|
# Check if the given value is valid using +valid_input?+ or
|
@@ -241,22 +258,12 @@ module Rails # :nodoc:
|
|
241
258
|
def validate!(*)
|
242
259
|
super if defined? super
|
243
260
|
|
244
|
-
raise NameError,
|
261
|
+
raise NameError, (+<<~MSG).squish if gql_name.start_with?('__') && !internal?
|
245
262
|
The name "#{gql_name}" is invalid. Only internal fields from the
|
246
263
|
spec can have a name starting with "__".
|
247
264
|
MSG
|
248
265
|
end
|
249
266
|
|
250
|
-
# Update the null value
|
251
|
-
def required!
|
252
|
-
@null = false
|
253
|
-
end
|
254
|
-
|
255
|
-
# Update the nullable value
|
256
|
-
def required_items!
|
257
|
-
@nullable = false
|
258
|
-
end
|
259
|
-
|
260
267
|
# Create a proxy of the current field
|
261
268
|
def to_proxy(*args, **xargs, &block)
|
262
269
|
proxy = self.class.allocate
|
@@ -266,16 +273,24 @@ module Rails # :nodoc:
|
|
266
273
|
proxy
|
267
274
|
end
|
268
275
|
|
269
|
-
|
270
|
-
|
271
|
-
|
272
|
-
|
276
|
+
# Check if the other field is equivalent
|
277
|
+
def =~(other)
|
278
|
+
other.is_a?(GraphQL::Field) &&
|
279
|
+
other.array? == array? &&
|
280
|
+
(other.null? == null? || other.null? && !null?) &&
|
281
|
+
(other.nullable? == nullable? || other.nullable? && !nullable?)
|
282
|
+
end
|
283
|
+
|
284
|
+
def inspect
|
285
|
+
(+<<~INFO).squish << '>'
|
286
|
+
#<GraphQL::#{self.class.name.split('::').last}
|
287
|
+
#{inspect_owner&.split(+'GraphQL::')&.last&.sub(+'::NestedTypes', '')}
|
273
288
|
#{inspect_source}
|
274
289
|
#{inspect_enabled}
|
275
290
|
#{gql_name}#{inspect_arguments}#{inspect_type}
|
276
291
|
#{inspect_default_value}
|
277
292
|
#{inspect_directives}
|
278
|
-
|
293
|
+
INFO
|
279
294
|
end
|
280
295
|
|
281
296
|
protected
|
@@ -304,9 +319,9 @@ module Rails # :nodoc:
|
|
304
319
|
end
|
305
320
|
end
|
306
321
|
|
307
|
-
#
|
308
|
-
def
|
309
|
-
|
322
|
+
# Check if the field was defined as an alternative class
|
323
|
+
def from_alternative?
|
324
|
+
proxied_owner.is_a?(Module) && proxied_owner <= Alternative::Query
|
310
325
|
end
|
311
326
|
|
312
327
|
# Show the name of the owner of the object for inspection
|
@@ -0,0 +1,89 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'globalid'
|
4
|
+
|
5
|
+
module Rails
|
6
|
+
module GraphQL
|
7
|
+
# = GraphQL Global ID
|
8
|
+
#
|
9
|
+
# GraphQL implementation of the Global ID that adds extended support to how
|
10
|
+
# things are located and stored. Mostly used for caching and custom access
|
11
|
+
# to the tree and request process.
|
12
|
+
#
|
13
|
+
# TODO: Implement signed operations
|
14
|
+
class GlobalID < ::GlobalID
|
15
|
+
SERIALIZER_KEY = "_gql_globalid"
|
16
|
+
|
17
|
+
# This adds support to ActiveJob serialization, which can be used to pass
|
18
|
+
# GraphQL objects to jobs and also deserialize things for subscriptions
|
19
|
+
class Serializer
|
20
|
+
include Singleton
|
21
|
+
|
22
|
+
class << self
|
23
|
+
delegate :serialize?, :serialize, :deserialize, to: :instance
|
24
|
+
end
|
25
|
+
|
26
|
+
# Determines if an argument should be serialized by this serializer.
|
27
|
+
def serialize?(argument)
|
28
|
+
argument.is_a?(Helpers::WithGlobalID) || argument.class.is_a?(Helpers::WithGlobalID)
|
29
|
+
end
|
30
|
+
|
31
|
+
# Serializes an argument to a JSON primitive type.
|
32
|
+
def serialize(argument)
|
33
|
+
{ GlobalID::SERIALIZER_KEY => argument.to_global_id.to_s }
|
34
|
+
end
|
35
|
+
|
36
|
+
# Deserializes an argument from a JSON primitive type.
|
37
|
+
def deserialize(argument)
|
38
|
+
GlobalID.find argument[GlobalID::SERIALIZER_KEY]
|
39
|
+
end
|
40
|
+
|
41
|
+
private
|
42
|
+
# The class of the object that will be serialized.
|
43
|
+
def klass
|
44
|
+
GlobalID
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
class << self
|
49
|
+
undef_method :app, :app=
|
50
|
+
|
51
|
+
# Create a new GraphQL Global identifier
|
52
|
+
def create(object, options = nil)
|
53
|
+
scope = options&.delete(:scope) || scope_of(object)
|
54
|
+
new(URI::GQL.create(object, scope, options), options)
|
55
|
+
end
|
56
|
+
|
57
|
+
# Find the scope on which the object is applied to
|
58
|
+
def scope_of(object)
|
59
|
+
object.try(:schema_type) if object.gid_base_class.is_a?(Helpers::WithSchemaFields)
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
undef_method :app, :model_name, :model_id
|
64
|
+
delegate :namespace, :class_name, :scope, :name, :instantiate?, to: :uri
|
65
|
+
|
66
|
+
def initialize(gid, options = {})
|
67
|
+
@uri = gid.is_a?(URI::GQL) ? gid : URI::GQL.parse(gid)
|
68
|
+
end
|
69
|
+
|
70
|
+
def find(options = {})
|
71
|
+
base_class.try(:find_by_gid, self)
|
72
|
+
end
|
73
|
+
|
74
|
+
def base_class
|
75
|
+
if %w[Schema Directive Type].include?(class_name)
|
76
|
+
GraphQL.const_get(class_name, false)
|
77
|
+
else
|
78
|
+
GraphQL.type_map.fetch(class_name, namespace: namespace)
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
def ==(other)
|
83
|
+
other.is_a?(GlobalID) && @uri == other.uri
|
84
|
+
end
|
85
|
+
|
86
|
+
alias eql? ==
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|
@@ -1,8 +1,8 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
module Rails
|
4
|
-
module GraphQL
|
5
|
-
module Helpers
|
3
|
+
module Rails
|
4
|
+
module GraphQL
|
5
|
+
module Helpers
|
6
6
|
# This is an extra magic on top of the delegator class from the standard
|
7
7
|
# lib that allows fetching a specific property of the delegated object
|
8
8
|
class AttributeDelegator < ActiveSupport::ProxyObject
|
@@ -14,11 +14,11 @@ module Rails # :nodoc:
|
|
14
14
|
|
15
15
|
private
|
16
16
|
|
17
|
-
def respond_to_missing?(method_name, include_private = false)
|
17
|
+
def respond_to_missing?(method_name, include_private = false)
|
18
18
|
__getobj__.respond_to?(method_name, include_private) || super
|
19
19
|
end
|
20
20
|
|
21
|
-
def method_missing(method_name, *args, **xargs, &block)
|
21
|
+
def method_missing(method_name, *args, **xargs, &block)
|
22
22
|
return super unless __getobj__.respond_to?(method_name)
|
23
23
|
__getobj__.public_send(method_name, *args, **xargs, &block)
|
24
24
|
end
|
@@ -0,0 +1,51 @@
|
|
1
|
+
module Rails
|
2
|
+
module GraphQL
|
3
|
+
module Helpers
|
4
|
+
# A inherited collection of arrays that can be unique when it is a set
|
5
|
+
class InheritedCollection::Array < InheritedCollection::Base
|
6
|
+
alias size count
|
7
|
+
alias to_ary eager
|
8
|
+
|
9
|
+
# Provide similar functionality of any? but returns the object instead
|
10
|
+
def find(value = nil, &block)
|
11
|
+
block ||= !value.is_a?(Module) ? value.method(:==) : ->(val) { val.class <= value }
|
12
|
+
reverse_each { |item| return item if block.call(item) }
|
13
|
+
nil
|
14
|
+
end
|
15
|
+
|
16
|
+
# Check if a given +value+ is included in any of the definitions
|
17
|
+
def include?(value)
|
18
|
+
each_definition.any? { |definition| definition.include?(value) }
|
19
|
+
end
|
20
|
+
|
21
|
+
# If any elements appears, the each block will run and return true
|
22
|
+
def empty?
|
23
|
+
lazy.each { return true }
|
24
|
+
false
|
25
|
+
end
|
26
|
+
|
27
|
+
# The normal each is the reverse each of the definitions
|
28
|
+
def each(&block)
|
29
|
+
lazy.reverse_each(&block)
|
30
|
+
end
|
31
|
+
|
32
|
+
# The reverse each is the normal each of the definitions
|
33
|
+
def reverse_each(&block)
|
34
|
+
block.nil? ? lazy : lazy.each(&block)
|
35
|
+
end
|
36
|
+
|
37
|
+
# Overrides the lazy operator
|
38
|
+
def lazy
|
39
|
+
(@type == :set) ? super.uniq : super
|
40
|
+
end
|
41
|
+
|
42
|
+
# Allow concatenating objects
|
43
|
+
def +(other)
|
44
|
+
result = to_a
|
45
|
+
result = result.to_set if @type == :set
|
46
|
+
result + other
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
@@ -0,0 +1,45 @@
|
|
1
|
+
module Rails
|
2
|
+
module GraphQL
|
3
|
+
module Helpers
|
4
|
+
# The base class for inherited collections. It helps softly dealing with
|
5
|
+
# values defined in multiple class instance variables and look up the tree
|
6
|
+
# to make it possible to iterate over combined result
|
7
|
+
class InheritedCollection::Base
|
8
|
+
include Enumerable
|
9
|
+
|
10
|
+
delegate :eager, to: :each
|
11
|
+
|
12
|
+
# Just a little helper to initialize the iterator form a given +source+
|
13
|
+
def self.handle(source, ivar, type)
|
14
|
+
klass = (type == :array || type == :set) ? :Array : :Hash
|
15
|
+
InheritedCollection.const_get(klass).new(source, ivar, type)
|
16
|
+
end
|
17
|
+
|
18
|
+
def initialize(source, ivar, type)
|
19
|
+
@source = source
|
20
|
+
@ivar = ivar
|
21
|
+
@type = type
|
22
|
+
end
|
23
|
+
|
24
|
+
# Overrides the lazy enumerator because each instance variable defined
|
25
|
+
# and found by the +each_definition+ will be iterated over lazily
|
26
|
+
def lazy
|
27
|
+
Enumerator::Lazy.new(each_definition) { |y, d| d.each(&y) }
|
28
|
+
end
|
29
|
+
|
30
|
+
protected
|
31
|
+
|
32
|
+
def each_definition
|
33
|
+
Enumerator.new do |yielder|
|
34
|
+
current = @source
|
35
|
+
until current === Object
|
36
|
+
yielder << current.instance_variable_get(@ivar) \
|
37
|
+
if current.instance_variable_defined?(@ivar)
|
38
|
+
current = current.superclass
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|