GrapQL Ruby: Custom Relay connection class for ActiveRecord::Relation objects
# This custom relay connection class exists because the built-in connection | |
# class is broken when max_page_size is used. | |
# | |
# See: https://github.com/rmosolgo/graphql-ruby/issues/1109 | |
class CustomArRelationRelayConnection < GraphQL::Relay::BaseConnection | |
def cursor_from_node(item) | |
cursor_col = item.class.implicit_order_column | |
encode(item.send(cursor_col).to_s) | |
end | |
def has_next_page | |
paged_nodes && @will_have_next_page | |
end | |
def has_previous_page | |
paged_nodes && @will_have_prev_page | |
end | |
private | |
def paged_nodes | |
return @computed_paged_nodes if defined? @computed_paged_nodes | |
@will_have_next_page = false | |
@will_have_prev_page = false | |
page = | |
ActiveRecord::Base.transaction do | |
rel = sliced_nodes | |
if first | |
if rel.count > first | |
@will_have_next_page = true | |
end | |
rel = rel.limit(first) | |
end | |
if last | |
skip = rel.count - last | |
if skip > 0 | |
rel = rel.offset(skip) | |
@will_have_prev_page = true | |
end | |
end | |
if max_page_size | |
if rel.count > max_page_size | |
rel = rel.limit(max_page_size) | |
@will_have_next_page = true | |
end | |
end | |
rel.to_a | |
end | |
@computed_paged_nodes = page | |
@computed_paged_nodes | |
end | |
def sliced_nodes | |
ActiveRecord::Base.transaction do | |
cursor_col = nodes.klass.implicit_order_column | |
rel = nodes | |
if after | |
after_val = decode(after) | |
rel = rel.where(rel.arel_table[cursor_col].gt(after_val)) | |
if nodes.where(nodes.arel_table[cursor_col].lteq(after_val)).exists? | |
@will_have_prev_page = true | |
end | |
end | |
if before | |
before_val = decode(before) | |
rel = rel.where(rel.arel_table[cursor_col].lt(before_val)) | |
if nodes.where(nodes.arel_table[cursor_col].gteq(before_val)).exists? | |
@will_have_next_page = true | |
end | |
end | |
rel | |
end | |
end | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
This comment has been minimized.
This implementation assumes:
implicit_order_column
value on the modelclass)
To use this: