moduleGraphQLmoduleRelay# Subclasses must implement:# - {#cursor_from_node}, which returns an opaque cursor for the given item# - {#sliced_nodes}, which slices by `before` & `after`# - {#paged_nodes}, which applies `first` & `last` limits## In a subclass, you have access to# - {#nodes}, the collection which the connection will wrap# - {#first}, {#after}, {#last}, {#before} (arguments passed to the field)# - {#max_page_size} (the specified maximum page size that can be returned from a connection)#classBaseConnectionextendGem::Deprecate# Just to encode data in the cursor, use something that won't conflictCURSOR_SEPARATOR="---"# Map of collection class names -> connection_classes# eg {"Array" => ArrayConnection}CONNECTION_IMPLEMENTATIONS={}class<<selfextendGem::Deprecate# Find a connection implementation suitable for exposing `nodes`## @param [Object] A collection of nodes (eg, Array, AR::Relation)# @return [subclass of BaseConnection] a connection Class for wrapping `nodes`defconnection_for_nodes(nodes)# Check for class _names_ because classes can be redefined in Rails developmentancestor_names=nodes.class.ancestors.map(&:name)implementation=CONNECTION_IMPLEMENTATIONS.finddo|nodes_class_name,connection_class|ancestor_names.include?nodes_class_nameendifimplementation.nil?raise("No connection implementation to wrap #{nodes.class} (#{nodes})")elseimplementation[1]endend# Add `connection_class` as the connection wrapper for `nodes_class`# eg, `RelationConnection` is the implementation for `AR::Relation`# @param [Class] A class representing a collection (eg, Array, AR::Relation)# @param [Class] A class implementing Connection methodsdefregister_connection_implementation(nodes_class,connection_class)CONNECTION_IMPLEMENTATIONS[nodes_class.name]=connection_classend# @deprecated use {#connection_for_nodes} insteadalias:connection_for_items:connection_for_nodesdeprecate(:connection_for_items,:connection_for_nodes,2016,9)endattr_reader:nodes,:arguments,:max_page_size,:parent,:field# Make a connection, wrapping `nodes`# @param [Object] The collection of nodes# @param Query arguments# @param field [Object] The underlying field# @param max_page_size [Int] The maximum number of results to return# @param parent [Object] The object which this collection belongs todefinitialize(nodes,arguments,field: nil,max_page_size: nil,parent: nil)@nodes=nodes@arguments=arguments@max_page_size=max_page_size@field=field@parent=parentend# @deprecated use {#nodes} insteadalias:object:nodesdeprecate(:object,:nodes,2016,9)# Provide easy access to provided arguments:METHODS_FROM_ARGUMENTS=[:first,:after,:last,:before,:order]# @!method first# The value passed as `first:`, if there was one# @!method after# The value passed as `after:`, if there was one# @!method last# The value passed as `last:`, if there was one# @!method before# The value passed as `before:`, if there was one# @!method order# The value passed as `order:`, if there was oneMETHODS_FROM_ARGUMENTS.eachdo|arg_name|define_method(arg_name)doarguments[arg_name]endend# These are the nodes to render for this connection,# probably wrapped by {GraphQL::Relay::Edge}defedge_nodes@edge_nodes||=paged_nodesend# Support the `pageInfo` fielddefpage_infoselfend# Used by `pageInfo`defhas_next_page!!(first&&sliced_nodes.count>first)end# Used by `pageInfo`defhas_previous_page!!(last&&sliced_nodes.count>last)end# Used by `pageInfo`defstart_cursorifstart_node=(respond_to?(:paged_nodes_array,true)?paged_nodes_array:paged_nodes).firstreturncursor_from_node(start_node)elsereturnnilendend# Used by `pageInfo`defend_cursorifend_node=(respond_to?(:paged_nodes_array,true)?paged_nodes_array:paged_nodes).lastreturncursor_from_node(end_node)elsereturnnilendend# An opaque operation which returns a connection-specific cursor.defcursor_from_node(object)raiseNotImplementedError,"must return a cursor for this object/connection pair"endprivatedefpaged_nodesraiseNotImplementedError,"must return nodes for this connection after paging"enddefsliced_nodesraiseNotImplementedError,"must return all nodes for this connection after chopping off first and last"endendendend