kirillplatonov / shopify_graphql

Less painful way to work with Shopify Graphql API in Ruby.
MIT License
63 stars 9 forks source link

Cursors and simplification #26

Closed resistorsoftware closed 1 year ago

resistorsoftware commented 1 year ago

I used to write two queries. One without the cursor and one with. I would call the one without a cursor to establish a first go-through, and then I would use the returned cursor if any with the second query that had a cursor...

Lo and behold, Shopify informed me of the error of my ways. You can include a nil cursor without penalty, meaning you need only write one query. Provide nil the first time through, and then after that, you have your after cursor...

I will rewrite your paging example with one query and if it all works as I expect, you can add that style to your list of examples if you want, where one query is good enough instead of needing two.

kirillplatonov commented 1 year ago

Please let me know if it will work out for you. It would be great to have only one query!

resistorsoftware commented 1 year ago

I use this call and as far as I can tell, it does what it should. The problem of course is not returning too much data!

A query in this case is some kind of date filter or order status. Notice that since the String attribute of the cursor is nil initially, it still works! Without the following exclamation, GraphQL forgives an attribute as optional. So we can use something like this to get back a resource with cursors: query = "created_at:>#{Time.now.days_ago(90).strftime("%Y-%m-%d")} AND financial_status:ANY -VOIDED" orders = GetOrdersForRewrite.call(query: query).data

class GetOrders include ShopifyGraphql::Query

QUERY = <<~GRAPHQL query($cursor: String, $query: String) { orders(first: 3, after: $cursor, query: $query) { pageInfo { endCursor hasNextPage } edges { node { id name createdAt taxesIncluded publication { name } displayFinancialStatus legacyResourceId lineItems(first: 20) { edges { node { id sku discountAllocations { allocatedAmountSet {shopMoney{amount}} } variant { id legacyResourceId barcode sku price displayName } quantity product { legacyResourceId handle title vendor isGiftCard } taxLines { rate ratePercentage } } } } } } } } GRAPHQL

def call(query) response = execute(QUERY) data = parse_data(response.data.orders.edges) while response.data.orders.pageInfo.hasNextPage response = execute(QUERY, cursor: response.data.orders.pageInfo.endCursor) data += parse_data(response.data.orders.edges) end response.data = data response end

def parse_data(data) return [] if data.blank?

data.compact.map do |edge| OpenStruct.new( id: edge.node.id, legacy_resource_id: edge.node.legacyResourceId, name: edge.node.name, source: edge.node.publication&.catalog&.title, taxes_included: edge.node.taxesIncluded, line_items: edge.node.lineItems.edges.map do |item_edge| OpenStruct.new( id: item_edge.node.id, sku: item_edge.node.sku, quantity: item_edge.node.quantity, price: item_edge.node&.variant&.price, variant_id: item_edge.node&.variant&.legacyResourceId, product_id: item_edge.node&.product&.legacyResourceId, is_gift_card: item_edge.node&.product&.isGiftCard, barcode: item_edge.node&.variant&.barcode, display_name: item_edge.node&.variant&.displayName, vendor: item_edge.node&.product&.vendor, ) end ) end end end

On Sat, Apr 29, 2023 at 1:56 AM Kirill Platonov @.***> wrote:

Please let me know if it will work out for you. It would be great to have only one query!

— Reply to this email directly, view it on GitHub https://github.com/kirillplatonov/shopify_graphql/issues/26#issuecomment-1528675662, or unsubscribe https://github.com/notifications/unsubscribe-auth/AAA6DK54F2OI3PQ2GCP5YHDXDSUQVANCNFSM6AAAAAAXPRWVOE . You are receiving this because you authored the thread.Message ID: @.***>

remy727 commented 1 year ago

Nice. Thank you for sharing. If I change the cursor type from String! to String, we can retrieve resources with just one query.

@kirillplatonov, I created #27 to update README with one query.