graphql 1.9.21 → 1.10.0.pre1

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.
Files changed (125) hide show
  1. checksums.yaml +4 -4
  2. data/lib/generators/graphql/core.rb +0 -1
  3. data/lib/generators/graphql/install_generator.rb +0 -1
  4. data/lib/generators/graphql/mutation_generator.rb +1 -1
  5. data/lib/generators/graphql/templates/base_field.erb +4 -0
  6. data/lib/generators/graphql/templates/graphql_controller.erb +0 -5
  7. data/lib/generators/graphql/templates/mutation.erb +1 -1
  8. data/lib/generators/graphql/templates/schema.erb +1 -1
  9. data/lib/graphql.rb +1 -11
  10. data/lib/graphql/analysis/ast.rb +2 -2
  11. data/lib/graphql/analysis/ast/analyzer.rb +4 -23
  12. data/lib/graphql/analysis/ast/max_query_complexity.rb +3 -3
  13. data/lib/graphql/analysis/ast/max_query_depth.rb +3 -7
  14. data/lib/graphql/analysis/ast/query_complexity.rb +2 -2
  15. data/lib/graphql/argument.rb +6 -2
  16. data/lib/graphql/backtrace/table.rb +10 -2
  17. data/lib/graphql/base_type.rb +5 -1
  18. data/lib/graphql/compatibility/query_parser_specification/parse_error_specification.rb +5 -9
  19. data/lib/graphql/define/assign_object_field.rb +2 -2
  20. data/lib/graphql/define/defined_object_proxy.rb +0 -3
  21. data/lib/graphql/define/instance_definable.rb +3 -14
  22. data/lib/graphql/enum_type.rb +4 -0
  23. data/lib/graphql/execution/directive_checks.rb +2 -2
  24. data/lib/graphql/execution/errors.rb +14 -15
  25. data/lib/graphql/execution/execute.rb +1 -1
  26. data/lib/graphql/execution/interpreter/runtime.rb +17 -39
  27. data/lib/graphql/execution/multiplex.rb +3 -3
  28. data/lib/graphql/field.rb +8 -0
  29. data/lib/graphql/filter.rb +1 -1
  30. data/lib/graphql/function.rb +1 -1
  31. data/lib/graphql/input_object_type.rb +1 -2
  32. data/lib/graphql/introspection/entry_points.rb +1 -2
  33. data/lib/graphql/introspection/input_value_type.rb +27 -9
  34. data/lib/graphql/introspection/schema_type.rb +1 -2
  35. data/lib/graphql/language/block_string.rb +2 -2
  36. data/lib/graphql/language/document_from_schema_definition.rb +5 -11
  37. data/lib/graphql/language/lexer.rb +48 -49
  38. data/lib/graphql/language/lexer.rl +48 -49
  39. data/lib/graphql/language/nodes.rb +11 -14
  40. data/lib/graphql/language/parser.rb +645 -650
  41. data/lib/graphql/language/parser.y +7 -8
  42. data/lib/graphql/language/token.rb +1 -1
  43. data/lib/graphql/non_null_type.rb +0 -10
  44. data/lib/graphql/pagination.rb +6 -0
  45. data/lib/graphql/pagination/active_record_relation_connection.rb +35 -0
  46. data/lib/graphql/pagination/array_connection.rb +78 -0
  47. data/lib/graphql/pagination/connection.rb +150 -0
  48. data/lib/graphql/pagination/connections.rb +103 -0
  49. data/lib/graphql/pagination/mongoid_relation_connection.rb +25 -0
  50. data/lib/graphql/pagination/relation_connection.rb +157 -0
  51. data/lib/graphql/pagination/sequel_dataset_connection.rb +28 -0
  52. data/lib/graphql/query.rb +1 -7
  53. data/lib/graphql/query/arguments.rb +3 -9
  54. data/lib/graphql/query/context.rb +9 -31
  55. data/lib/graphql/query/literal_input.rb +29 -10
  56. data/lib/graphql/query/null_context.rb +0 -4
  57. data/lib/graphql/query/variable_validation_error.rb +1 -1
  58. data/lib/graphql/query/variables.rb +2 -4
  59. data/lib/graphql/relay/base_connection.rb +7 -3
  60. data/lib/graphql/relay/edges_instrumentation.rb +1 -1
  61. data/lib/graphql/relay/node.rb +2 -2
  62. data/lib/graphql/relay/relation_connection.rb +5 -9
  63. data/lib/graphql/schema.rb +27 -68
  64. data/lib/graphql/schema/argument.rb +31 -5
  65. data/lib/graphql/schema/base_64_bp.rb +2 -3
  66. data/lib/graphql/schema/build_from_definition.rb +113 -179
  67. data/lib/graphql/schema/build_from_definition/resolve_map.rb +10 -4
  68. data/lib/graphql/schema/build_from_definition/resolve_map/default_resolve.rb +1 -1
  69. data/lib/graphql/schema/directive.rb +6 -7
  70. data/lib/graphql/schema/directive/feature.rb +1 -1
  71. data/lib/graphql/schema/enum.rb +1 -0
  72. data/lib/graphql/schema/enum_value.rb +4 -1
  73. data/lib/graphql/schema/field.rb +37 -39
  74. data/lib/graphql/schema/field/connection_extension.rb +11 -1
  75. data/lib/graphql/schema/input_object.rb +2 -5
  76. data/lib/graphql/schema/interface.rb +2 -0
  77. data/lib/graphql/schema/introspection_system.rb +1 -4
  78. data/lib/graphql/schema/loader.rb +6 -12
  79. data/lib/graphql/schema/member.rb +2 -0
  80. data/lib/graphql/schema/member/base_dsl_methods.rb +2 -2
  81. data/lib/graphql/schema/member/build_type.rb +4 -0
  82. data/lib/graphql/schema/member/cached_graphql_definition.rb +5 -0
  83. data/lib/graphql/schema/member/has_ast_node.rb +17 -0
  84. data/lib/graphql/schema/member/has_fields.rb +10 -16
  85. data/lib/graphql/schema/member/instrumentation.rb +1 -6
  86. data/lib/graphql/schema/member/type_system_helpers.rb +1 -1
  87. data/lib/graphql/schema/mutation.rb +1 -1
  88. data/lib/graphql/schema/object.rb +5 -6
  89. data/lib/graphql/schema/possible_types.rb +3 -3
  90. data/lib/graphql/schema/printer.rb +1 -3
  91. data/lib/graphql/schema/relay_classic_mutation.rb +2 -6
  92. data/lib/graphql/schema/resolver.rb +5 -35
  93. data/lib/graphql/schema/scalar.rb +1 -0
  94. data/lib/graphql/schema/subscription.rb +6 -6
  95. data/lib/graphql/schema/timeout_middleware.rb +2 -3
  96. data/lib/graphql/schema/type_expression.rb +27 -17
  97. data/lib/graphql/schema/union.rb +7 -26
  98. data/lib/graphql/schema/validation.rb +1 -17
  99. data/lib/graphql/schema/warden.rb +3 -77
  100. data/lib/graphql/schema/wrapper.rb +1 -1
  101. data/lib/graphql/static_validation/definition_dependencies.rb +12 -21
  102. data/lib/graphql/static_validation/rules/argument_literals_are_compatible.rb +9 -4
  103. data/lib/graphql/static_validation/rules/arguments_are_defined.rb +10 -7
  104. data/lib/graphql/static_validation/rules/directives_are_in_valid_locations.rb +1 -1
  105. data/lib/graphql/static_validation/rules/fields_have_appropriate_selections.rb +5 -5
  106. data/lib/graphql/static_validation/rules/fields_will_merge.rb +4 -4
  107. data/lib/graphql/static_validation/rules/required_input_object_attributes_are_present.rb +3 -3
  108. data/lib/graphql/static_validation/rules/variable_default_values_are_correctly_typed.rb +3 -3
  109. data/lib/graphql/static_validation/rules/variable_usages_are_allowed.rb +5 -6
  110. data/lib/graphql/static_validation/rules/variables_are_input_types.rb +1 -1
  111. data/lib/graphql/static_validation/rules/variables_are_used_and_defined.rb +1 -1
  112. data/lib/graphql/subscriptions.rb +7 -7
  113. data/lib/graphql/subscriptions/action_cable_subscriptions.rb +2 -2
  114. data/lib/graphql/subscriptions/event.rb +5 -19
  115. data/lib/graphql/subscriptions/instrumentation.rb +9 -4
  116. data/lib/graphql/subscriptions/subscription_root.rb +2 -10
  117. data/lib/graphql/tracing/skylight_tracing.rb +0 -1
  118. data/lib/graphql/types/int.rb +1 -1
  119. data/lib/graphql/types/relay/base_connection.rb +3 -1
  120. data/lib/graphql/union_type.rb +23 -58
  121. data/lib/graphql/upgrader/member.rb +1 -1
  122. data/lib/graphql/version.rb +1 -1
  123. metadata +20 -13
  124. data/lib/generators/graphql/templates/base_mutation.erb +0 -8
  125. data/lib/graphql/schema/type_membership.rb +0 -34
@@ -77,8 +77,11 @@ rule
77
77
  }
78
78
 
79
79
  type:
80
+ nullable_type { return val[0] }
81
+ | nullable_type BANG { return make_node(:NonNullType, of_type: val[0]) }
82
+
83
+ nullable_type:
80
84
  name { return make_node(:TypeName, name: val[0])}
81
- | type BANG { return make_node(:NonNullType, of_type: val[0]) }
82
85
  | LBRACKET type RBRACKET { return make_node(:ListType, of_type: val[1]) }
83
86
 
84
87
  default_value_opt:
@@ -165,7 +168,6 @@ rule
165
168
 
166
169
  arguments_opt:
167
170
  /* none */ { return EMPTY_ARRAY }
168
- | LPAREN RPAREN { return EMPTY_ARRAY }
169
171
  | LPAREN arguments_list RPAREN { return val[1] }
170
172
 
171
173
  arguments_list:
@@ -187,7 +189,7 @@ rule
187
189
  | object_literal_value
188
190
 
189
191
  input_value:
190
- | literal_value
192
+ literal_value
191
193
  | variable
192
194
  | object_value
193
195
 
@@ -440,7 +442,6 @@ def initialize(query_string, filename:, tracer: Tracing::NullTracer)
440
442
  @query_string = query_string
441
443
  @filename = filename
442
444
  @tracer = tracer
443
- @reused_next_token = [nil, nil]
444
445
  end
445
446
 
446
447
  def parse_document
@@ -452,7 +453,7 @@ def parse_document
452
453
  # From the tokens, build an AST
453
454
  @tracer.trace("parse", {query_string: @query_string}) do
454
455
  if @tokens.empty?
455
- make_node(:Document, definitions: [], filename: @filename)
456
+ raise GraphQL::ParseError.new("Unexpected end of document", nil, nil, @query_string)
456
457
  else
457
458
  do_parse
458
459
  end
@@ -471,9 +472,7 @@ def next_token
471
472
  if lexer_token.nil?
472
473
  nil
473
474
  else
474
- @reused_next_token[0] = lexer_token.name
475
- @reused_next_token[1] = lexer_token
476
- @reused_next_token
475
+ [lexer_token.name, lexer_token]
477
476
  end
478
477
  end
479
478
 
@@ -14,7 +14,7 @@ module GraphQL
14
14
  attr_reader :value
15
15
  attr_reader :prev_token, :line, :col
16
16
 
17
- def initialize(name, value, line, col, prev_token)
17
+ def initialize(value:, name:, line:, col:, prev_token:)
18
18
  @name = name
19
19
  @value = -value
20
20
  @line = line
@@ -1,8 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
  module GraphQL
3
- class DoubleNonNullTypeError < GraphQL::Error
4
- end
5
-
6
3
  # A non-null type modifies another type.
7
4
  #
8
5
  # Non-null types can be created with `!` (`InnerType!`)
@@ -37,13 +34,6 @@ module GraphQL
37
34
 
38
35
  attr_reader :of_type
39
36
  def initialize(of_type:)
40
- if of_type.is_a?(GraphQL::NonNullType)
41
- raise(
42
- DoubleNonNullTypeError,
43
- "You tried to add a non-null constraint twice (!! instead of !)"
44
- )
45
- end
46
-
47
37
  super()
48
38
  @of_type = of_type
49
39
  end
@@ -0,0 +1,6 @@
1
+ # frozen_string_literal: true
2
+ require "graphql/pagination/array_connection"
3
+ require "graphql/pagination/active_record_relation_connection"
4
+ require "graphql/pagination/connections"
5
+ require "graphql/pagination/mongoid_relation_connection"
6
+ require "graphql/pagination/sequel_dataset_connection"
@@ -0,0 +1,35 @@
1
+ # frozen_string_literal: true
2
+ require "graphql/pagination/relation_connection"
3
+
4
+ module GraphQL
5
+ module Pagination
6
+ # Customizes `RelationConnection` to work with `ActiveRecord::Relation`s.
7
+ class ActiveRecordRelationConnection < Pagination::RelationConnection
8
+ def relation_count(relation)
9
+ if relation.respond_to?(:unscope)
10
+ relation.unscope(:order).count(:all)
11
+ else
12
+ # Rails 3
13
+ relation.count
14
+ end
15
+ end
16
+
17
+ def relation_limit(relation)
18
+ relation.limit_value
19
+ end
20
+
21
+ def relation_offset(relation)
22
+ relation.offset_value
23
+ end
24
+
25
+ def null_relation(relation)
26
+ if relation.respond_to?(:none)
27
+ relation.none
28
+ else
29
+ # Rails 3
30
+ relation.where("1=2")
31
+ end
32
+ end
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,78 @@
1
+ # frozen_string_literal: true
2
+ require "graphql/pagination/connection"
3
+
4
+ module GraphQL
5
+ module Pagination
6
+ class ArrayConnection < Pagination::Connection
7
+ def nodes
8
+ load_nodes
9
+ @nodes
10
+ end
11
+
12
+ def has_previous_page
13
+ load_nodes
14
+ @has_previous_page
15
+ end
16
+
17
+ def has_next_page
18
+ load_nodes
19
+ @has_next_page
20
+ end
21
+
22
+ def cursor_for(item)
23
+ idx = items.find_index(item) + 1
24
+ context.schema.cursor_encoder.encode(idx.to_s)
25
+ end
26
+
27
+ private
28
+
29
+ def index_from_cursor(cursor)
30
+ decode(cursor).to_i
31
+ end
32
+
33
+ # Populate all the pagination info _once_,
34
+ # It doesn't do anything on subsequent calls.
35
+ def load_nodes
36
+ @nodes ||= begin
37
+ sliced_nodes = if before && after
38
+ items[index_from_cursor(after)..index_from_cursor(before)-1] || []
39
+ elsif before
40
+ items[0..index_from_cursor(before)-2] || []
41
+ elsif after
42
+ items[index_from_cursor(after)..-1] || []
43
+ else
44
+ items
45
+ end
46
+
47
+ @has_previous_page = if last
48
+ # There are items preceding the ones in this result
49
+ sliced_nodes.count > last
50
+ elsif after
51
+ # We've paginated into the Array a bit, there are some behind us
52
+ index_from_cursor(after) > 0
53
+ else
54
+ false
55
+ end
56
+
57
+ @has_next_page = if first
58
+ # There are more items after these items
59
+ sliced_nodes.count > first
60
+ elsif before
61
+ # The original array is longer than the `before` index
62
+ index_from_cursor(before) < items.length
63
+ else
64
+ false
65
+ end
66
+
67
+ limited_nodes = sliced_nodes
68
+
69
+ limited_nodes = limited_nodes.first(first) if first
70
+ limited_nodes = limited_nodes.last(last) if last
71
+ limited_nodes = limited_nodes.first(max_page_size) if max_page_size && !first && !last
72
+
73
+ limited_nodes
74
+ end
75
+ end
76
+ end
77
+ end
78
+ end
@@ -0,0 +1,150 @@
1
+ # frozen_string_literal: true
2
+
3
+ module GraphQL
4
+ module Pagination
5
+ # A Connection wraps a list of items and provides cursor-based pagination over it.
6
+ #
7
+ # Connections were introduced by Facebook's `Relay` front-end framework, but
8
+ # proved to be generally useful for GraphQL APIs. When in doubt, use connections
9
+ # to serve lists (like Arrays, ActiveRecord::Relations) via GraphQL.
10
+ #
11
+ # Unlike the previous connection implementation, these default to bidirectional pagination.
12
+ #
13
+ # Pagination arguments and context may be provided at initialization or assigned later (see {Schema::Field::ConnectionExtension}).
14
+ class Connection
15
+ class PaginationImplementationMissingError < GraphQL::Error
16
+ end
17
+
18
+ # @return [Class] The class to use for wrapping items as `edges { ... }`. Defaults to `Connection::Edge`
19
+ def self.edge_class
20
+ self::Edge
21
+ end
22
+
23
+ # @return [Object] A list object, from the application. This is the unpaginated value passed into the connection.
24
+ attr_reader :items
25
+
26
+ # @return [GraphQL::Query::Context]
27
+ attr_accessor :context
28
+
29
+ attr_accessor :before, :after
30
+
31
+ # @param items [Object] some unpaginated collection item, like an `Array` or `ActiveRecord::Relation`
32
+ # @param context [Query::Context]
33
+ # @param first [Integer, nil] The limit parameter from the client, if it provided one
34
+ # @param after [String, nil] A cursor for pagination, if the client provided one
35
+ # @param last [Integer, nil] Limit parameter from the client, if provided
36
+ # @param before [String, nil] A cursor for pagination, if the client provided one.
37
+ def initialize(items, context: nil, first: nil, after: nil, max_page_size: nil, last: nil, before: nil)
38
+ @items = items
39
+ @context = context
40
+ @first = first
41
+ @after = after
42
+ @last = last
43
+ @before = before
44
+ @max_page_size = max_page_size
45
+ end
46
+
47
+ attr_writer :max_page_size
48
+ def max_page_size
49
+ @max_page_size ||= context.schema.default_max_page_size
50
+ end
51
+
52
+ attr_writer :first
53
+ # @return [Integer, nil] a clamped `first` value. (The underlying instance variable doesn't have limits on it)
54
+ def first
55
+ limit_pagination_argument(@first, max_page_size)
56
+ end
57
+
58
+ attr_writer :last
59
+ # @return [Integer, nil] a clamped `last` value. (The underlying instance variable doesn't have limits on it)
60
+ def last
61
+ limit_pagination_argument(@last, max_page_size)
62
+ end
63
+
64
+ # @return [Array<Edge>] {nodes}, but wrapped with Edge instances
65
+ def edges
66
+ @edges ||= nodes.map { |n| self.class.edge_class.new(n, self) }
67
+ end
68
+
69
+ # @return [Array<Object>] A slice of {items}, constrained by {@first}/{@after}/{@last}/{@before}
70
+ def nodes
71
+ raise PaginationImplementationMissingError, "Implement #{self.class}#nodes to paginate `@items`"
72
+ end
73
+
74
+ # A dynamic alias for compatibility with {Relay::BaseConnection}.
75
+ # @deprecated use {#nodes} instead
76
+ def edge_nodes
77
+ nodes
78
+ end
79
+
80
+ # The connection object itself implements `PageInfo` fields
81
+ def page_info
82
+ self
83
+ end
84
+
85
+ # @return [Boolean] True if there are more items after this page
86
+ def has_next_page
87
+ raise PaginationImplementationMissingError, "Implement #{self.class}#has_next_page to return the next-page check"
88
+ end
89
+
90
+ # @return [Boolean] True if there were items before these items
91
+ def has_previous_page
92
+ raise PaginationImplementationMissingError, "Implement #{self.class}#has_previous_page to return the previous-page check"
93
+ end
94
+
95
+ # @return [String] The cursor of the first item in {nodes}
96
+ def start_cursor
97
+ nodes.first && cursor_for(nodes.first)
98
+ end
99
+
100
+ # @return [String] The cursor of the last item in {nodes}
101
+ def end_cursor
102
+ nodes.last && cursor_for(nodes.last)
103
+ end
104
+
105
+ # Return a cursor for this item.
106
+ # @param item [Object] one of the passed in {items}, taken from {nodes}
107
+ # @return [String]
108
+ def cursor_for(item)
109
+ raise PaginationImplementationMissingError, "Implement #{self.class}#cursor_for(item) to return the cursor for #{item.inspect}"
110
+ end
111
+
112
+ private
113
+
114
+ # @param argument [nil, Integer] `first` or `last`, as provided by the client
115
+ # @param max_page_size [nil, Integer]
116
+ # @return [nil, Integer] `nil` if the input was `nil`, otherwise a value between `0` and `max_page_size`
117
+ def limit_pagination_argument(argument, max_page_size)
118
+ if argument
119
+ if argument < 0
120
+ argument = 0
121
+ elsif max_page_size && argument > max_page_size
122
+ argument = max_page_size
123
+ end
124
+ end
125
+ argument
126
+ end
127
+
128
+ def decode(cursor)
129
+ context.schema.cursor_encoder.decode(cursor)
130
+ end
131
+
132
+ # A wrapper around paginated items. It includes a {cursor} for pagination
133
+ # and could be extended with custom relationship-level data.
134
+ class Edge
135
+ def initialize(item, connection)
136
+ @connection = connection
137
+ @item = item
138
+ end
139
+
140
+ def node
141
+ @item
142
+ end
143
+
144
+ def cursor
145
+ @connection.cursor_for(@item)
146
+ end
147
+ end
148
+ end
149
+ end
150
+ end
@@ -0,0 +1,103 @@
1
+ # frozen_string_literal: true
2
+
3
+ module GraphQL
4
+ module Pagination
5
+ # A schema-level connection wrapper manager.
6
+ #
7
+ # Attach as a plugin.
8
+ #
9
+ # @example Using new default connections
10
+ # class MySchema < GraphQL::Schema
11
+ # use GraphQL::Pagination::Connections
12
+ # end
13
+ #
14
+ # @example Adding a custom wrapper
15
+ # class MySchema < GraphQL::Schema
16
+ # use GraphQL::Pagination::Connections
17
+ # connections.add(MyApp::SearchResults, MyApp::SearchResultsConnection)
18
+ # end
19
+ #
20
+ # @example Removing default connection support for arrays (they can still be manually wrapped)
21
+ # class MySchema < GraphQL::Schema
22
+ # use GraphQL::Pagination::Connections
23
+ # connections.delete(Array)
24
+ # end
25
+ #
26
+ # @see {Schema.connections}
27
+ class Connections
28
+ class ImplementationMissingError < GraphQL::Error
29
+ end
30
+
31
+ def self.use(schema_defn)
32
+ [schema_defn.target, schema_defn.target.class].each do |schema|
33
+ schema.connections = self.new
34
+ end
35
+ end
36
+
37
+ def initialize
38
+ @wrappers = {}
39
+ add_default
40
+ end
41
+
42
+ def add(nodes_class, implementation)
43
+ @wrappers[nodes_class] = implementation
44
+ end
45
+
46
+ def delete(nodes_class)
47
+ @wrappers.delete(nodes_class)
48
+ end
49
+
50
+ # Used by the runtime to wrap values in connection wrappers.
51
+ # @api Private
52
+ def wrap(field, object, arguments, context)
53
+ impl = nil
54
+ object.class.ancestors.each { |cls|
55
+ impl = @wrappers[cls]
56
+ break if impl
57
+ }
58
+
59
+ if impl.nil?
60
+ raise ImplementationMissingError, "Couldn't find a connection wrapper for #{object.class} during #{field.path} (#{object.inspect})"
61
+ end
62
+
63
+ impl.new(
64
+ object,
65
+ context: context,
66
+ max_page_size: field.max_page_size || context.schema.default_max_page_size,
67
+ first: arguments[:first],
68
+ after: arguments[:after],
69
+ last: arguments[:last],
70
+ before: arguments[:before],
71
+ )
72
+ end
73
+
74
+ private
75
+
76
+ def add_default
77
+ add(Array, Pagination::ArrayConnection)
78
+
79
+ if defined?(ActiveRecord::Relation)
80
+ add(ActiveRecord::Relation, Pagination::ActiveRecordRelationConnection)
81
+ end
82
+
83
+ if defined?(Sequel::Dataset)
84
+ add(Sequel::Dataset, Pagination::SequelDatasetConnection)
85
+ end
86
+
87
+ if defined?(Mongoid::Criteria)
88
+ add(Mongoid::Criteria, Pagination::MongoidRelationConnection)
89
+ end
90
+
91
+ # Mongoid 5 and 6
92
+ if defined?(Mongoid::Relations::Targets::Enumerable)
93
+ add(Mongoid::Relations::Targets::Enumerable, Pagination::MongoidRelationConnection)
94
+ end
95
+
96
+ # Mongoid 7
97
+ if defined?(Mongoid::Association::Referenced::HasMany::Targets::Enumerable)
98
+ add(Mongoid::Association::Referenced::HasMany::Targets::Enumerable, Pagination::MongoidRelationConnection)
99
+ end
100
+ end
101
+ end
102
+ end
103
+ end