Last active
October 28, 2019 16:51
-
-
Save dteoh/bf063050ee3298910c70f2af1c61c879 to your computer and use it in GitHub Desktop.
GrapQL Ruby: Custom Relay connection class for ActiveRecord::Relation objects
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# 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 implementation assumes:
implicit_order_column
value on the modelclass)
To use this: