lib/graphql/relay/relation_connection.rb in graphql-relay-0.8.1 vs lib/graphql/relay/relation_connection.rb in graphql-relay-0.9.0
- old
+ new
@@ -1,20 +1,13 @@
module GraphQL
module Relay
class RelationConnection < BaseConnection
- DEFAULT_ORDER = "id"
-
def cursor_from_node(item)
- order_value = item.public_send(order_name)
- cursor_parts = [order, order_value]
- Base64.strict_encode64(cursor_parts.join(CURSOR_SEPARATOR))
+ offset = starting_offset + paged_nodes_array.index(item) + 1
+ Base64.strict_encode64(offset.to_s)
end
- def order
- @order ||= (super || DEFAULT_ORDER)
- end
-
def has_next_page
!!(first && sliced_nodes.limit(first + 1).count > first)
end
# Used by `pageInfo`
@@ -24,77 +17,64 @@
private
# apply first / last limit results
def paged_nodes
- @paged_nodes = begin
+ @paged_nodes ||= begin
items = sliced_nodes
- limit = [first, last, max_page_size].compact.min
- first && items = items.first(limit)
- last && items.count > last && items = items.last(limit)
- items
+ items.limit(limit)
end
end
# Apply cursors to edges
def sliced_nodes
@sliced_nodes ||= begin
items = object
+ items.offset(starting_offset)
+ end
+ end
- if order
- items = items.order(items.table[order_name].public_send(order_direction))
- end
+ def offset_from_cursor(cursor)
+ Base64.decode64(cursor).to_i
+ end
- if after
- _o, order_value = slice_from_cursor(after)
- direction_marker = order_direction == :asc ? ">" : "<"
- where_condition = create_order_condition(table_name, order_name, order_value, direction_marker)
- items = items.where(where_condition)
- end
-
+ def starting_offset
+ @initial_offset ||= begin
if before
- _o, order_value = slice_from_cursor(before)
- direction_marker = order_direction == :asc ? "<" : ">"
- where_condition = create_order_condition(table_name, order_name, order_value, direction_marker)
- items = items.where(where_condition)
+ [previous_offset, 0].max
+ else
+ previous_offset
end
-
- items
end
end
- def slice_from_cursor(cursor)
- decoded = Base64.decode64(cursor)
- order, order_value = decoded.split(CURSOR_SEPARATOR)
+ # Offset from the previous selection, if there was one
+ # Otherwise, zero
+ def previous_offset
+ @previous_offset ||= if after
+ offset_from_cursor(after)
+ elsif before
+ offset_from_cursor(before) - last - 1
+ else
+ 0
+ end
end
- # Remove possible direction marker:
- def order_name
- @order_name ||= order.sub(/^-/, '')
- end
-
- # Check for direction marker
- def order_direction
- @order_direction ||= order.start_with?("-") ? :desc : :asc
- end
-
- def table_name
- @table_name ||= object.table.table_name
- end
-
- # When creating the where constraint, cast the value to correct column data type so
- # active record can send it in correct format to db
- def create_order_condition(table, column, value, direction_marker)
- table_name = ActiveRecord::Base.connection.quote_table_name(table)
- name = ActiveRecord::Base.connection.quote_column_name(column)
- if ActiveRecord::VERSION::MAJOR == 5
- casted_value = object.table.able_to_type_cast? ? object.table.type_cast_for_database(column, value) : value
- elsif ActiveRecord::VERSION::MAJOR == 4 && ActiveRecord::VERSION::MINOR >= 2
- casted_value = object.table.engine.columns_hash[column].cast_type.type_cast_from_user(value)
+ def limit
+ @limit ||= if first
+ [first, max_page_size].compact.min
else
- casted_value = object.table.engine.columns_hash[column].type_cast(value)
+ last_limit = if previous_offset <= 0
+ previous_offset + last
+ else
+ last
+ end
+ [last_limit, max_page_size].compact.min
end
- ["#{table_name}.#{name} #{direction_marker} ?", casted_value]
+ end
+
+ def paged_nodes_array
+ @paged_nodes_array ||= paged_nodes.to_a
end
end
if defined?(ActiveRecord)